@propbinder/mobile-design 0.2.8 → 0.2.10

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.
@@ -755,16 +755,16 @@ class DsMobileListItemComponent {
755
755
  if (isPlatformBrowser(this.platformId)) {
756
756
  // Show button on tablet breakpoint and above (768px+)
757
757
  const isDesktopViewport = window.innerWidth >= 768;
758
- console.log('[ListItem] Desktop detection:', {
759
- innerWidth: window.innerWidth,
760
- isDesktopViewport
761
- });
758
+ // console.log('[ListItem] Desktop detection:', {
759
+ // innerWidth: window.innerWidth,
760
+ // isDesktopViewport
761
+ // });
762
762
  this.isDesktop.set(isDesktopViewport);
763
763
  // Listen for window resize to update detection
764
764
  window.addEventListener('resize', () => {
765
765
  const newIsDesktop = window.innerWidth >= 768;
766
766
  if (newIsDesktop !== this.isDesktop()) {
767
- console.log('[ListItem] Viewport changed, updating desktop detection:', newIsDesktop);
767
+ // console.log('[ListItem] Viewport changed, updating desktop detection:', newIsDesktop);
768
768
  this.isDesktop.set(newIsDesktop);
769
769
  }
770
770
  });
@@ -870,15 +870,15 @@ class DsMobileListItemComponent {
870
870
  * Handle click events
871
871
  */
872
872
  handleClick(event) {
873
- console.log('[ListItem] Click event fired', {
874
- interactive: this.interactive(),
875
- disabled: this.disabled(),
876
- loading: this.loading(),
877
- longPressTriggered: this.longPressTriggered,
878
- target: event.target
879
- });
873
+ // console.log('[ListItem] Click event fired', {
874
+ // interactive: this.interactive(),
875
+ // disabled: this.disabled(),
876
+ // loading: this.loading(),
877
+ // longPressTriggered: this.longPressTriggered,
878
+ // target: event.target
879
+ // });
880
880
  if (!this.interactive() || this.disabled() || this.loading()) {
881
- console.log('[ListItem] Click ignored - not interactive or disabled/loading');
881
+ // console.log('[ListItem] Click ignored - not interactive or disabled/loading');
882
882
  return;
883
883
  }
884
884
  // Don't emit click if it came from an interactive child element
@@ -887,15 +887,15 @@ class DsMobileListItemComponent {
887
887
  const closestInteractive = target.closest('button, a, input, select, textarea, [role="button"]');
888
888
  // Check if the interactive element is a child, not the host itself
889
889
  if (closestInteractive && closestInteractive !== event.currentTarget) {
890
- console.log('[ListItem] Click ignored - came from interactive child:', closestInteractive);
890
+ // console.log('[ListItem] Click ignored - came from interactive child:', closestInteractive);
891
891
  return;
892
892
  }
893
893
  if (!this.longPressTriggered) {
894
- console.log('[ListItem] Emitting itemClick');
894
+ // console.log('[ListItem] Emitting itemClick');
895
895
  this.itemClick.emit();
896
896
  }
897
897
  else {
898
- console.log('[ListItem] Click ignored - long press was triggered');
898
+ // console.log('[ListItem] Click ignored - long press was triggered');
899
899
  }
900
900
  this.longPressTriggered = false;
901
901
  }
@@ -926,7 +926,7 @@ class DsMobileListItemComponent {
926
926
  * Emits moreButtonClick for parent components to handle
927
927
  */
928
928
  handleMoreButtonClick(event) {
929
- console.log('[ListItem] Desktop more button clicked');
929
+ // console.log('[ListItem] Desktop more button clicked');
930
930
  // Stop propagation to prevent triggering itemClick
931
931
  event.stopPropagation();
932
932
  event.preventDefault();
@@ -939,42 +939,43 @@ class DsMobileListItemComponent {
939
939
  <div class="content-leading">
940
940
  <ng-content select="[content-leading]" />
941
941
  </div>
942
-
942
+
943
943
  <div class="content-main">
944
944
  @if (title()) {
945
- <h3 class="structured-title">{{ title() }}</h3>
946
- }
947
- @if (subtitle()) {
948
- <p class="structured-subtitle">{{ subtitle() }}</p>
945
+ <h3 class="structured-title">{{ title() }}</h3>
946
+ } @if (subtitle()) {
947
+ <p class="structured-subtitle">{{ subtitle() }}</p>
949
948
  }
950
-
949
+
951
950
  <ng-content select="[content-main]" />
952
951
  <ng-content />
953
952
  </div>
954
-
953
+
955
954
  <div class="content-trailing">
956
- @if (interactive() && enableLongPress() && showDesktopMoreButton() && isDesktop()) {
957
- <ds-icon-button
958
- class="desktop-more-button"
959
- icon="remixMoreFill"
960
- variant="secondary"
961
- size="sm"
962
- (clicked)="handleMoreButtonClick($event)"
963
- aria-label="More options">
964
- </ds-icon-button>
955
+ @if (interactive() && enableLongPress() && showDesktopMoreButton() &&
956
+ isDesktop()) {
957
+ <ds-icon-button
958
+ class="desktop-more-button"
959
+ icon="remixMoreFill"
960
+ variant="secondary"
961
+ size="sm"
962
+ (clicked)="handleMoreButtonClick($event)"
963
+ aria-label="More options"
964
+ >
965
+ </ds-icon-button>
965
966
  }
966
967
  <ng-content select="[content-trailing]" />
967
968
  </div>
968
969
  </div>
969
- `, isInline: true, styles: [":host{display:block;position:relative;padding:var(--item-padding-top, 12px) 0 var(--item-padding-bottom, 12px) 0;box-sizing:border-box;--leading-size: 32px;--content-gap: 12px;--interactive-offset: 8px}:host:after{content:\"\";position:absolute;bottom:0;left:calc(var(--leading-size) + var(--content-gap));right:0;height:1px;background:var(--border-color-default, #e5e5e5);z-index:1;display:var(--divider-display, block)}:host(.no-divider):after{display:none}.list-item-inner{display:flex;flex-direction:row;align-items:flex-start;gap:var(--content-gap);position:relative}:host(.align-center) .list-item-inner{align-items:center}:host(.align-bottom) .list-item-inner{align-items:flex-end}:host(.interactive) .list-item-inner:before{content:\"\";position:absolute;top:calc(-1 * var(--interactive-offset));left:calc(-1 * var(--interactive-offset));right:calc(-1 * var(--interactive-offset));bottom:calc(-1 * var(--interactive-offset));background:var(--color-background-neutral-primary, #ffffff);border-radius:16px;z-index:-1;pointer-events:none}:host(.interactive){cursor:pointer}@media (hover: hover) and (pointer: fine){:host(.interactive):hover .list-item-inner:before{background:var(--color-background-neutral-primary-hover, #f5f5f5)}}:host(.interactive):active .list-item-inner:before{background:var(--color-background-neutral-primary-hover, #f5f5f5)}:host(.interactive):focus-visible{outline:none}:host(.interactive):focus-visible .list-item-inner:before{outline:2px solid var(--color-brand-primary, #5d5fef);outline-offset:2px}:host(.disabled){opacity:.5;pointer-events:none}:host(.loading){pointer-events:none}:host(.variant-compact) .list-item-inner{gap:8px}.content-leading{flex-shrink:0;width:var(--leading-size);height:var(--leading-size);display:flex;align-items:flex-start;justify-content:center;position:relative;z-index:1}:host(.align-center) .content-leading{align-items:center}:host(.align-bottom) .content-leading{align-items:flex-end}.content-main{flex:1;min-width:0;display:flex;flex-direction:column;gap:8px;position:relative;z-index:1;justify-content:flex-start}:host(.align-center) .content-main{justify-content:center}:host(.align-bottom) .content-main{justify-content:flex-end}.content-trailing{flex-shrink:0;display:flex;align-items:flex-start;position:relative;z-index:1}.structured-title{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm, 14px);font-weight:600;line-height:20px;letter-spacing:-.3px;color:var(--text-color-default-primary, #202227);margin:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.structured-subtitle{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm, 14px);font-weight:400;line-height:20px;letter-spacing:-.3px;color:var(--text-color-default-secondary, #545B66);margin:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.desktop-more-button::ng-deep button{border-radius:50%!important}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: DsIconButtonComponent, selector: "ds-icon-button", inputs: ["variant", "size", "icon", "disabled", "loading", "pressed", "expanded", "ariaLabel", "tooltip", "tooltipDisabled", "tooltipPlacement"], outputs: ["clicked", "focused", "blurred"] }] });
970
+ `, isInline: true, styles: [":host{display:block;position:relative;padding:var(--item-padding-top, 12px) 0 var(--item-padding-bottom, 12px) 0;box-sizing:border-box;--leading-size: 32px;--content-gap: 12px;--interactive-offset: 8px}:host:after{content:\"\";position:absolute;bottom:0;left:calc(var(--leading-size) + var(--content-gap));right:0;height:1px;background:var(--border-color-default, #e5e5e5);z-index:1;display:var(--divider-display, block)}:host(.no-divider):after{display:none}.list-item-inner{display:flex;flex-direction:row;align-items:flex-start;gap:var(--content-gap);position:relative}:host(.align-center) .list-item-inner{align-items:center}:host(.align-bottom) .list-item-inner{align-items:flex-end}:host(.interactive) .list-item-inner:before{content:\"\";position:absolute;top:calc(-1 * var(--interactive-offset));left:calc(-1 * var(--interactive-offset));right:calc(-1 * var(--interactive-offset));bottom:calc(-1 * var(--interactive-offset));background:var(--color-background-neutral-primary, #ffffff);border-radius:16px;z-index:-1;pointer-events:none}:host(.interactive){cursor:pointer}@media (hover: hover) and (pointer: fine){:host(.interactive):hover .list-item-inner:before{background:var(--color-background-neutral-primary-hover, #f5f5f5)}}:host(.interactive):active .list-item-inner:before{background:var(--color-background-neutral-primary-hover, #f5f5f5)}:host(.interactive):focus-visible{outline:none}:host(.interactive):focus-visible .list-item-inner:before{outline:2px solid var(--color-brand-primary, #5d5fef);outline-offset:2px}:host(.disabled){opacity:.5;pointer-events:none}:host(.loading){pointer-events:none}:host(.variant-compact) .list-item-inner{gap:8px}.content-leading{flex-shrink:0;width:var(--leading-size);height:var(--leading-size);display:flex;align-items:flex-start;justify-content:center;position:relative;z-index:1}:host(.align-center) .content-leading{align-items:center}:host(.align-bottom) .content-leading{align-items:flex-end}.content-main{flex:1;min-width:0;display:flex;flex-direction:column;gap:8px;position:relative;z-index:1;justify-content:flex-start}:host(.align-center) .content-main{justify-content:center}:host(.align-bottom) .content-main{justify-content:flex-end}.content-trailing{flex-shrink:0;display:flex;align-items:flex-start;position:relative;z-index:1}.structured-title{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm, 14px);font-weight:600;line-height:20px;letter-spacing:-.3px;color:var(--text-color-default-primary, #202227);margin:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.structured-subtitle{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm, 14px);font-weight:400;line-height:20px;letter-spacing:-.3px;color:var(--text-color-default-secondary, #545b66);margin:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.desktop-more-button::ng-deep button{border-radius:50%!important}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: DsIconButtonComponent, selector: "ds-icon-button", inputs: ["variant", "size", "icon", "disabled", "loading", "pressed", "expanded", "ariaLabel", "tooltip", "tooltipDisabled", "tooltipPlacement"], outputs: ["clicked", "focused", "blurred"] }] });
970
971
  }
971
972
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsMobileListItemComponent, decorators: [{
972
973
  type: Component,
973
974
  args: [{ selector: 'ds-mobile-list-item', standalone: true, imports: [CommonModule, DsIconButtonComponent], hostDirectives: [
974
975
  {
975
976
  directive: DsMobileLongPressDirective,
976
- outputs: ['longPress']
977
- }
977
+ outputs: ['longPress'],
978
+ },
978
979
  ], host: {
979
980
  '[class.interactive]': 'interactive() && !disabled()',
980
981
  '[class.disabled]': 'disabled()',
@@ -993,40 +994,41 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
993
994
  '(click)': 'handleClick($event)',
994
995
  '(keydown.enter)': 'handleKeyDown($event)',
995
996
  '(keydown.space)': 'handleKeyDown($event)',
996
- '(longPress)': 'handleLongPress()'
997
+ '(longPress)': 'handleLongPress()',
997
998
  }, template: `
998
999
  <div class="list-item-inner">
999
1000
  <div class="content-leading">
1000
1001
  <ng-content select="[content-leading]" />
1001
1002
  </div>
1002
-
1003
+
1003
1004
  <div class="content-main">
1004
1005
  @if (title()) {
1005
- <h3 class="structured-title">{{ title() }}</h3>
1006
- }
1007
- @if (subtitle()) {
1008
- <p class="structured-subtitle">{{ subtitle() }}</p>
1006
+ <h3 class="structured-title">{{ title() }}</h3>
1007
+ } @if (subtitle()) {
1008
+ <p class="structured-subtitle">{{ subtitle() }}</p>
1009
1009
  }
1010
-
1010
+
1011
1011
  <ng-content select="[content-main]" />
1012
1012
  <ng-content />
1013
1013
  </div>
1014
-
1014
+
1015
1015
  <div class="content-trailing">
1016
- @if (interactive() && enableLongPress() && showDesktopMoreButton() && isDesktop()) {
1017
- <ds-icon-button
1018
- class="desktop-more-button"
1019
- icon="remixMoreFill"
1020
- variant="secondary"
1021
- size="sm"
1022
- (clicked)="handleMoreButtonClick($event)"
1023
- aria-label="More options">
1024
- </ds-icon-button>
1016
+ @if (interactive() && enableLongPress() && showDesktopMoreButton() &&
1017
+ isDesktop()) {
1018
+ <ds-icon-button
1019
+ class="desktop-more-button"
1020
+ icon="remixMoreFill"
1021
+ variant="secondary"
1022
+ size="sm"
1023
+ (clicked)="handleMoreButtonClick($event)"
1024
+ aria-label="More options"
1025
+ >
1026
+ </ds-icon-button>
1025
1027
  }
1026
1028
  <ng-content select="[content-trailing]" />
1027
1029
  </div>
1028
1030
  </div>
1029
- `, styles: [":host{display:block;position:relative;padding:var(--item-padding-top, 12px) 0 var(--item-padding-bottom, 12px) 0;box-sizing:border-box;--leading-size: 32px;--content-gap: 12px;--interactive-offset: 8px}:host:after{content:\"\";position:absolute;bottom:0;left:calc(var(--leading-size) + var(--content-gap));right:0;height:1px;background:var(--border-color-default, #e5e5e5);z-index:1;display:var(--divider-display, block)}:host(.no-divider):after{display:none}.list-item-inner{display:flex;flex-direction:row;align-items:flex-start;gap:var(--content-gap);position:relative}:host(.align-center) .list-item-inner{align-items:center}:host(.align-bottom) .list-item-inner{align-items:flex-end}:host(.interactive) .list-item-inner:before{content:\"\";position:absolute;top:calc(-1 * var(--interactive-offset));left:calc(-1 * var(--interactive-offset));right:calc(-1 * var(--interactive-offset));bottom:calc(-1 * var(--interactive-offset));background:var(--color-background-neutral-primary, #ffffff);border-radius:16px;z-index:-1;pointer-events:none}:host(.interactive){cursor:pointer}@media (hover: hover) and (pointer: fine){:host(.interactive):hover .list-item-inner:before{background:var(--color-background-neutral-primary-hover, #f5f5f5)}}:host(.interactive):active .list-item-inner:before{background:var(--color-background-neutral-primary-hover, #f5f5f5)}:host(.interactive):focus-visible{outline:none}:host(.interactive):focus-visible .list-item-inner:before{outline:2px solid var(--color-brand-primary, #5d5fef);outline-offset:2px}:host(.disabled){opacity:.5;pointer-events:none}:host(.loading){pointer-events:none}:host(.variant-compact) .list-item-inner{gap:8px}.content-leading{flex-shrink:0;width:var(--leading-size);height:var(--leading-size);display:flex;align-items:flex-start;justify-content:center;position:relative;z-index:1}:host(.align-center) .content-leading{align-items:center}:host(.align-bottom) .content-leading{align-items:flex-end}.content-main{flex:1;min-width:0;display:flex;flex-direction:column;gap:8px;position:relative;z-index:1;justify-content:flex-start}:host(.align-center) .content-main{justify-content:center}:host(.align-bottom) .content-main{justify-content:flex-end}.content-trailing{flex-shrink:0;display:flex;align-items:flex-start;position:relative;z-index:1}.structured-title{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm, 14px);font-weight:600;line-height:20px;letter-spacing:-.3px;color:var(--text-color-default-primary, #202227);margin:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.structured-subtitle{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm, 14px);font-weight:400;line-height:20px;letter-spacing:-.3px;color:var(--text-color-default-secondary, #545B66);margin:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.desktop-more-button::ng-deep button{border-radius:50%!important}\n"] }]
1031
+ `, styles: [":host{display:block;position:relative;padding:var(--item-padding-top, 12px) 0 var(--item-padding-bottom, 12px) 0;box-sizing:border-box;--leading-size: 32px;--content-gap: 12px;--interactive-offset: 8px}:host:after{content:\"\";position:absolute;bottom:0;left:calc(var(--leading-size) + var(--content-gap));right:0;height:1px;background:var(--border-color-default, #e5e5e5);z-index:1;display:var(--divider-display, block)}:host(.no-divider):after{display:none}.list-item-inner{display:flex;flex-direction:row;align-items:flex-start;gap:var(--content-gap);position:relative}:host(.align-center) .list-item-inner{align-items:center}:host(.align-bottom) .list-item-inner{align-items:flex-end}:host(.interactive) .list-item-inner:before{content:\"\";position:absolute;top:calc(-1 * var(--interactive-offset));left:calc(-1 * var(--interactive-offset));right:calc(-1 * var(--interactive-offset));bottom:calc(-1 * var(--interactive-offset));background:var(--color-background-neutral-primary, #ffffff);border-radius:16px;z-index:-1;pointer-events:none}:host(.interactive){cursor:pointer}@media (hover: hover) and (pointer: fine){:host(.interactive):hover .list-item-inner:before{background:var(--color-background-neutral-primary-hover, #f5f5f5)}}:host(.interactive):active .list-item-inner:before{background:var(--color-background-neutral-primary-hover, #f5f5f5)}:host(.interactive):focus-visible{outline:none}:host(.interactive):focus-visible .list-item-inner:before{outline:2px solid var(--color-brand-primary, #5d5fef);outline-offset:2px}:host(.disabled){opacity:.5;pointer-events:none}:host(.loading){pointer-events:none}:host(.variant-compact) .list-item-inner{gap:8px}.content-leading{flex-shrink:0;width:var(--leading-size);height:var(--leading-size);display:flex;align-items:flex-start;justify-content:center;position:relative;z-index:1}:host(.align-center) .content-leading{align-items:center}:host(.align-bottom) .content-leading{align-items:flex-end}.content-main{flex:1;min-width:0;display:flex;flex-direction:column;gap:8px;position:relative;z-index:1;justify-content:flex-start}:host(.align-center) .content-main{justify-content:center}:host(.align-bottom) .content-main{justify-content:flex-end}.content-trailing{flex-shrink:0;display:flex;align-items:flex-start;position:relative;z-index:1}.structured-title{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm, 14px);font-weight:600;line-height:20px;letter-spacing:-.3px;color:var(--text-color-default-primary, #202227);margin:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.structured-subtitle{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm, 14px);font-weight:400;line-height:20px;letter-spacing:-.3px;color:var(--text-color-default-secondary, #545b66);margin:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.desktop-more-button::ng-deep button{border-radius:50%!important}\n"] }]
1030
1032
  }], ctorParameters: () => [], propDecorators: { leadingSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "leadingSize", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], align: [{ type: i0.Input, args: [{ isSignal: true, alias: "align", required: false }] }], interactive: [{ type: i0.Input, args: [{ isSignal: true, alias: "interactive", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], enableLongPress: [{ type: i0.Input, args: [{ isSignal: true, alias: "enableLongPress", required: false }] }], showDesktopMoreButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "showDesktopMoreButton", required: false }] }], interactiveOffset: [{ type: i0.Input, args: [{ isSignal: true, alias: "interactiveOffset", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], subtitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "subtitle", required: false }] }], showDivider: [{ type: i0.Input, args: [{ isSignal: true, alias: "showDivider", required: false }] }], dividerSpacing: [{ type: i0.Input, args: [{ isSignal: true, alias: "dividerSpacing", required: false }] }], itemClick: [{ type: i0.Output, args: ["itemClick"] }], moreButtonClick: [{ type: i0.Output, args: ["moreButtonClick"] }] } });
1031
1033
 
1032
1034
  /**
@@ -3028,7 +3030,7 @@ class WhitelabelDemoModalService {
3028
3030
  */
3029
3031
  async open() {
3030
3032
  try {
3031
- console.log('[WhitelabelDemoModal] Opening...');
3033
+ // console.log('[WhitelabelDemoModal] Opening...');
3032
3034
  const modal = await this.modalController.create({
3033
3035
  component: WhitelabelDemoModalComponent,
3034
3036
  cssClass: 'ds-whitelabel-demo-modal',
@@ -3040,14 +3042,14 @@ class WhitelabelDemoModalService {
3040
3042
  keyboardClose: true,
3041
3043
  // Control the presenting element animation
3042
3044
  enterAnimation: undefined, // Use default
3043
- leaveAnimation: undefined // Use default
3045
+ leaveAnimation: undefined, // Use default
3044
3046
  });
3045
- console.log('[WhitelabelDemoModal] Modal created, presenting...');
3047
+ // console.log('[WhitelabelDemoModal] Modal created, presenting...');
3046
3048
  await modal.present();
3047
- console.log('[WhitelabelDemoModal] Modal presented');
3049
+ // console.log('[WhitelabelDemoModal] Modal presented');
3048
3050
  }
3049
3051
  catch (error) {
3050
- console.error('[WhitelabelDemoModal] Error opening modal:', error);
3052
+ // console.error('[WhitelabelDemoModal] Error opening modal:', error);
3051
3053
  throw error;
3052
3054
  }
3053
3055
  }
@@ -3074,7 +3076,7 @@ class WhitelabelDemoModalService {
3074
3076
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: WhitelabelDemoModalService, decorators: [{
3075
3077
  type: Injectable,
3076
3078
  args: [{
3077
- providedIn: 'root'
3079
+ providedIn: 'root',
3078
3080
  }]
3079
3081
  }], ctorParameters: () => [{ type: i1.ModalController }] });
3080
3082
 
@@ -9838,8 +9840,8 @@ class DsMobileModalService {
9838
9840
  * ```
9839
9841
  */
9840
9842
  async open(options) {
9841
- console.log('[Modal] Opening modal with options:', options);
9842
- const { component, componentProps, cssClass, presentationStyle = 'card', backdropDismiss = true, showBackdrop = true, keyboardClose = true, swipeToClose, initialBreakpoint, breakpoints, animated = true, mode = 'ios', handleNavigationBack = true } = options;
9843
+ // console.log('[Modal] Opening modal with options:', options);
9844
+ const { component, componentProps, cssClass, presentationStyle = 'card', backdropDismiss = true, showBackdrop = true, keyboardClose = true, swipeToClose, initialBreakpoint, breakpoints, animated = true, mode = 'ios', handleNavigationBack = true, } = options;
9843
9845
  // Build modal configuration
9844
9846
  const modalConfig = {
9845
9847
  component,
@@ -9872,9 +9874,9 @@ class DsMobileModalService {
9872
9874
  };
9873
9875
  }
9874
9876
  const modal = await this.modalController.create(modalConfig);
9875
- console.log('[Modal] Modal created, presenting...');
9877
+ // console.log('[Modal] Modal created, presenting...');
9876
9878
  await modal.present();
9877
- console.log('[Modal] Modal presented');
9879
+ // console.log('[Modal] Modal presented');
9878
9880
  return modal;
9879
9881
  }
9880
9882
  /**
@@ -9895,7 +9897,7 @@ class DsMobileModalService {
9895
9897
  componentProps,
9896
9898
  presentationStyle: 'fullscreen',
9897
9899
  backdropDismiss: false,
9898
- showBackdrop: false
9900
+ showBackdrop: false,
9899
9901
  });
9900
9902
  }
9901
9903
  /**
@@ -9916,7 +9918,7 @@ class DsMobileModalService {
9916
9918
  componentProps,
9917
9919
  presentationStyle: 'card',
9918
9920
  backdropDismiss: true,
9919
- showBackdrop: true
9921
+ showBackdrop: true,
9920
9922
  });
9921
9923
  }
9922
9924
  /**
@@ -9945,7 +9947,7 @@ class DsMobileModalService {
9945
9947
  showBackdrop: true,
9946
9948
  swipeToClose: options?.swipeToClose ?? true,
9947
9949
  initialBreakpoint: options?.initialBreakpoint ?? 0.5,
9948
- breakpoints: options?.breakpoints ?? [0, 0.5, 0.75, 1]
9950
+ breakpoints: options?.breakpoints ?? [0, 0.5, 0.75, 1],
9949
9951
  });
9950
9952
  }
9951
9953
  /**
@@ -10019,7 +10021,7 @@ class DsMobileModalService {
10019
10021
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsMobileModalService, decorators: [{
10020
10022
  type: Injectable,
10021
10023
  args: [{
10022
- providedIn: 'root'
10024
+ providedIn: 'root',
10023
10025
  }]
10024
10026
  }], ctorParameters: () => [{ type: i1.ModalController }] });
10025
10027
 
@@ -11621,8 +11623,8 @@ class DsMobilePostDetailModalService extends BaseModalService {
11621
11623
  * @returns Promise that resolves when the modal is presented
11622
11624
  */
11623
11625
  async open(postData, options) {
11624
- console.log('[PostDetailModal] Opening with data:', postData);
11625
- console.log('[PostDetailModal] options.onSubmitComment =', options?.onSubmitComment);
11626
+ // console.log('[PostDetailModal] Opening with data:', postData);
11627
+ // console.log('[PostDetailModal] options.onSubmitComment =', options?.onSubmitComment);
11626
11628
  const modal = await this.createModal(DsMobilePostDetailModalComponent, {
11627
11629
  postData: postData,
11628
11630
  loading: options?.loading ?? false,
@@ -11634,9 +11636,9 @@ class DsMobilePostDetailModalService extends BaseModalService {
11634
11636
  }, {
11635
11637
  keyboardClose: true, // Keep keyboard close behavior for this modal
11636
11638
  });
11637
- console.log('[PostDetailModal] Modal created, presenting...');
11639
+ // console.log('[PostDetailModal] Modal created, presenting...');
11638
11640
  await modal.present();
11639
- console.log('[PostDetailModal] Modal presented');
11641
+ // console.log('[PostDetailModal] Modal presented');
11640
11642
  }
11641
11643
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsMobilePostDetailModalService, deps: [{ token: i1.ModalController }], target: i0.ɵɵFactoryTarget.Injectable });
11642
11644
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsMobilePostDetailModalService, providedIn: 'root' });
@@ -12082,7 +12084,7 @@ class DsMobileCardInlineFileComponent {
12082
12084
  */
12083
12085
  fileName = input('Document', ...(ngDevMode ? [{ debugName: "fileName" }] : []));
12084
12086
  /**
12085
- * File size display (e.g., "1.2 MB")
12087
+ * File size display (e.g., '1.2 MB')
12086
12088
  */
12087
12089
  fileSize = input('', ...(ngDevMode ? [{ debugName: "fileSize" }] : []));
12088
12090
  /**
@@ -12097,6 +12099,11 @@ class DsMobileCardInlineFileComponent {
12097
12099
  * - 'compact' - Reduced padding and row layout
12098
12100
  */
12099
12101
  layout = input('default', ...(ngDevMode ? [{ debugName: "layout" }] : []));
12102
+ /**
12103
+ * Optional URL to open when clicked
12104
+ * If provided, clicking the card will open this URL in a new tab
12105
+ */
12106
+ fileUrl = input(undefined, ...(ngDevMode ? [{ debugName: "fileUrl" }] : []));
12100
12107
  /**
12101
12108
  * Emits when the file attachment is clicked
12102
12109
  */
@@ -12105,7 +12112,9 @@ class DsMobileCardInlineFileComponent {
12105
12112
  * Get the appropriate icon name based on variant
12106
12113
  */
12107
12114
  getIconName() {
12108
- return this.variant() === 'pdf' ? 'remixFileTextLine' : 'remixAttachmentLine';
12115
+ return this.variant() === 'pdf'
12116
+ ? 'remixFileTextLine'
12117
+ : 'remixAttachmentLine';
12109
12118
  }
12110
12119
  /**
12111
12120
  * Get the file type label based on variant
@@ -12114,73 +12123,87 @@ class DsMobileCardInlineFileComponent {
12114
12123
  return this.variant() === 'pdf' ? 'PDF' : 'DOC';
12115
12124
  }
12116
12125
  handleClick() {
12126
+ const url = this.fileUrl();
12127
+ console.log(url);
12128
+ if (url) {
12129
+ window.open(url, '_blank', 'noopener,noreferrer');
12130
+ }
12117
12131
  this.fileClick.emit();
12118
12132
  }
12119
12133
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsMobileCardInlineFileComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
12120
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: DsMobileCardInlineFileComponent, isStandalone: true, selector: "ds-mobile-card-inline-file", inputs: { fileName: { classPropertyName: "fileName", publicName: "fileName", isSignal: true, isRequired: false, transformFunction: null }, fileSize: { classPropertyName: "fileSize", publicName: "fileSize", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, layout: { classPropertyName: "layout", publicName: "layout", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { fileClick: "fileClick" }, ngImport: i0, template: `
12121
- <ds-mobile-card-inline
12122
- [variant]="layout()"
12123
- (cardClick)="handleClick()">
12124
-
12125
- <div content-leading class="item-avatar" [class.pdf]="variant() === 'pdf'" [class.doc]="variant() === 'doc'">
12134
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: DsMobileCardInlineFileComponent, isStandalone: true, selector: "ds-mobile-card-inline-file", inputs: { fileName: { classPropertyName: "fileName", publicName: "fileName", isSignal: true, isRequired: false, transformFunction: null }, fileSize: { classPropertyName: "fileSize", publicName: "fileSize", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, layout: { classPropertyName: "layout", publicName: "layout", isSignal: true, isRequired: false, transformFunction: null }, fileUrl: { classPropertyName: "fileUrl", publicName: "fileUrl", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { fileClick: "fileClick" }, ngImport: i0, template: `
12135
+ <ds-mobile-card-inline [variant]="layout()" (cardClick)="handleClick()">
12136
+ <div
12137
+ content-leading
12138
+ class="item-avatar"
12139
+ [class.pdf]="variant() === 'pdf'"
12140
+ [class.doc]="variant() === 'doc'"
12141
+ >
12126
12142
  <ds-avatar
12127
12143
  type="icon"
12128
12144
  [iconName]="getIconName()"
12129
12145
  [size]="layout() === 'compact' ? 'sm' : 'md'"
12130
12146
  />
12131
12147
  </div>
12132
-
12148
+
12133
12149
  <div content-main class="item-content">
12134
12150
  <div class="item-name">{{ fileName() }}</div>
12135
12151
  @if (fileSize()) {
12136
- <div class="item-meta">{{ getFileTypeLabel() }} · {{ fileSize() }}</div>
12152
+ <div class="item-meta">{{ getFileTypeLabel() }} · {{ fileSize() }}</div>
12137
12153
  } @else {
12138
- <div class="item-meta">{{ getFileTypeLabel() }}</div>
12154
+ <div class="item-meta">{{ getFileTypeLabel() }}</div>
12139
12155
  }
12140
12156
  </div>
12141
-
12142
- <ds-icon
12157
+
12158
+ <ds-icon
12143
12159
  content-trailing
12144
- name="remixArrowRightSLine"
12160
+ name="remixArrowRightSLine"
12145
12161
  size="20px"
12146
12162
  class="item-trailing"
12147
12163
  />
12148
12164
  </ds-mobile-card-inline>
12149
- `, isInline: true, styles: [".item-avatar.pdf ::ng-deep .avatar--icon{background-color:#ff5757!important}.item-avatar.doc ::ng-deep .avatar--icon{background-color:var(--color-blue-base, #3B82F6)!important}\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"] }, { kind: "component", type: DsMobileCardInlineComponent, selector: "ds-mobile-card-inline", inputs: ["variant", "disabled"], outputs: ["cardClick"] }] });
12165
+ `, isInline: true, styles: [".item-avatar.pdf ::ng-deep .avatar--icon{background-color:#ff5757!important}.item-avatar.doc ::ng-deep .avatar--icon{background-color:var(--color-blue-base, #3b82f6)!important}\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"] }, { kind: "component", type: DsMobileCardInlineComponent, selector: "ds-mobile-card-inline", inputs: ["variant", "disabled"], outputs: ["cardClick"] }] });
12150
12166
  }
12151
12167
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsMobileCardInlineFileComponent, decorators: [{
12152
12168
  type: Component,
12153
- args: [{ selector: 'ds-mobile-card-inline-file', standalone: true, imports: [CommonModule, DsAvatarComponent, DsIconComponent, DsMobileCardInlineComponent], template: `
12154
- <ds-mobile-card-inline
12155
- [variant]="layout()"
12156
- (cardClick)="handleClick()">
12157
-
12158
- <div content-leading class="item-avatar" [class.pdf]="variant() === 'pdf'" [class.doc]="variant() === 'doc'">
12169
+ args: [{ selector: 'ds-mobile-card-inline-file', standalone: true, imports: [
12170
+ CommonModule,
12171
+ DsAvatarComponent,
12172
+ DsIconComponent,
12173
+ DsMobileCardInlineComponent,
12174
+ ], template: `
12175
+ <ds-mobile-card-inline [variant]="layout()" (cardClick)="handleClick()">
12176
+ <div
12177
+ content-leading
12178
+ class="item-avatar"
12179
+ [class.pdf]="variant() === 'pdf'"
12180
+ [class.doc]="variant() === 'doc'"
12181
+ >
12159
12182
  <ds-avatar
12160
12183
  type="icon"
12161
12184
  [iconName]="getIconName()"
12162
12185
  [size]="layout() === 'compact' ? 'sm' : 'md'"
12163
12186
  />
12164
12187
  </div>
12165
-
12188
+
12166
12189
  <div content-main class="item-content">
12167
12190
  <div class="item-name">{{ fileName() }}</div>
12168
12191
  @if (fileSize()) {
12169
- <div class="item-meta">{{ getFileTypeLabel() }} · {{ fileSize() }}</div>
12192
+ <div class="item-meta">{{ getFileTypeLabel() }} · {{ fileSize() }}</div>
12170
12193
  } @else {
12171
- <div class="item-meta">{{ getFileTypeLabel() }}</div>
12194
+ <div class="item-meta">{{ getFileTypeLabel() }}</div>
12172
12195
  }
12173
12196
  </div>
12174
-
12175
- <ds-icon
12197
+
12198
+ <ds-icon
12176
12199
  content-trailing
12177
- name="remixArrowRightSLine"
12200
+ name="remixArrowRightSLine"
12178
12201
  size="20px"
12179
12202
  class="item-trailing"
12180
12203
  />
12181
12204
  </ds-mobile-card-inline>
12182
- `, styles: [".item-avatar.pdf ::ng-deep .avatar--icon{background-color:#ff5757!important}.item-avatar.doc ::ng-deep .avatar--icon{background-color:var(--color-blue-base, #3B82F6)!important}\n"] }]
12183
- }], propDecorators: { fileName: [{ type: i0.Input, args: [{ isSignal: true, alias: "fileName", required: false }] }], fileSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "fileSize", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], layout: [{ type: i0.Input, args: [{ isSignal: true, alias: "layout", required: false }] }], fileClick: [{ type: i0.Output, args: ["fileClick"] }] } });
12205
+ `, styles: [".item-avatar.pdf ::ng-deep .avatar--icon{background-color:#ff5757!important}.item-avatar.doc ::ng-deep .avatar--icon{background-color:var(--color-blue-base, #3b82f6)!important}\n"] }]
12206
+ }], propDecorators: { fileName: [{ type: i0.Input, args: [{ isSignal: true, alias: "fileName", required: false }] }], fileSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "fileSize", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], layout: [{ type: i0.Input, args: [{ isSignal: true, alias: "layout", required: false }] }], fileUrl: [{ type: i0.Input, args: [{ isSignal: true, alias: "fileUrl", required: false }] }], fileClick: [{ type: i0.Output, args: ["fileClick"] }] } });
12184
12207
 
12185
12208
  /**
12186
12209
  * DsMobileSystemMessageBannerComponent
@@ -12384,7 +12407,7 @@ class DsMobileChatModalComponent {
12384
12407
  // Track keyboard state
12385
12408
  this.isKeyboardVisible = true;
12386
12409
  // Check if user is near bottom before auto-scrolling
12387
- this.isNearBottom().then(isNear => {
12410
+ this.isNearBottom().then((isNear) => {
12388
12411
  if (isNear) {
12389
12412
  // User is already viewing latest messages, maintain that position
12390
12413
  // Small delay to synchronize with keyboard animation
@@ -12443,7 +12466,7 @@ class DsMobileChatModalComponent {
12443
12466
  avatarType: this.currentUserAvatarType(),
12444
12467
  avatarSrc: this.currentUserAvatarSrc(),
12445
12468
  fileAttachments: event.attachments || [],
12446
- isNewMessage: true // Mark as new message to trigger animation
12469
+ isNewMessage: true, // Mark as new message to trigger animation
12447
12470
  };
12448
12471
  // Add message to list
12449
12472
  const updatedMessages = [...this.messages(), newMessage];
@@ -12451,7 +12474,7 @@ class DsMobileChatModalComponent {
12451
12474
  // Remove the isNewMessage flag after animation completes (using spring-bouncy duration ~600ms)
12452
12475
  setTimeout(() => {
12453
12476
  const msgs = this.messages();
12454
- const msgIndex = msgs.findIndex(m => m.id === newMessage.id);
12477
+ const msgIndex = msgs.findIndex((m) => m.id === newMessage.id);
12455
12478
  if (msgIndex !== -1) {
12456
12479
  msgs[msgIndex].isNewMessage = false;
12457
12480
  this.messages.set([...msgs]);
@@ -12508,7 +12531,10 @@ class DsMobileChatModalComponent {
12508
12531
  timestamp: this.formatMessageTimestamp(ownerMessage.timestamp),
12509
12532
  avatarInitials: ownerMessage.avatarInitials,
12510
12533
  avatarSrc: ownerMessage.avatarSrc,
12511
- avatarType: ownerMessage.avatarType === 'photo' || ownerMessage.avatarType === 'initials' ? ownerMessage.avatarType : undefined,
12534
+ avatarType: ownerMessage.avatarType === 'photo' ||
12535
+ ownerMessage.avatarType === 'initials'
12536
+ ? ownerMessage.avatarType
12537
+ : undefined,
12512
12538
  }
12513
12539
  : undefined;
12514
12540
  this.lightboxService.openImages({
@@ -12545,7 +12571,7 @@ class DsMobileChatModalComponent {
12545
12571
  requestAnimationFrame(() => {
12546
12572
  requestAnimationFrame(() => {
12547
12573
  setTimeout(() => {
12548
- this.isNearBottom().then(isNear => {
12574
+ this.isNearBottom().then((isNear) => {
12549
12575
  if (isNear) {
12550
12576
  // User is at bottom, maintain that position as composer expands
12551
12577
  this.scrollToBottom();
@@ -12565,7 +12591,7 @@ class DsMobileChatModalComponent {
12565
12591
  .then(() => {
12566
12592
  this.isKeyboardVisible = false;
12567
12593
  })
12568
- .catch(e => console.log('[ChatModal] Keyboard.hide() not available:', e));
12594
+ .catch((e) => console.log('[ChatModal] Keyboard.hide() not available:', e));
12569
12595
  }
12570
12596
  /**
12571
12597
  * Get file variant for card-inline-file component
@@ -12585,26 +12611,28 @@ class DsMobileChatModalComponent {
12585
12611
  */
12586
12612
  async handleImageClick(attachment, message) {
12587
12613
  await this.lightboxService.openImages({
12588
- images: [{
12614
+ images: [
12615
+ {
12589
12616
  type: 'image',
12590
12617
  src: attachment.src,
12591
12618
  title: attachment.name || 'Image',
12592
- alt: attachment.name || 'Chat image'
12593
- }],
12619
+ alt: attachment.name || 'Chat image',
12620
+ },
12621
+ ],
12594
12622
  author: {
12595
12623
  name: message.senderName,
12596
12624
  role: message.senderRole,
12597
12625
  avatarInitials: message.avatarInitials,
12598
12626
  avatarType: message.avatarType === 'initials' ? 'initials' : 'photo',
12599
12627
  avatarSrc: message.avatarSrc,
12600
- timestamp: this.formatMessageTimestamp(message.timestamp)
12628
+ timestamp: this.formatMessageTimestamp(message.timestamp),
12601
12629
  },
12602
12630
  initialIndex: 0,
12603
12631
  enableZoom: true,
12604
12632
  showControls: false,
12605
12633
  enableSwipe: false,
12606
12634
  showInfo: false,
12607
- showActions: false
12635
+ showActions: false,
12608
12636
  });
12609
12637
  }
12610
12638
  /**
@@ -12625,7 +12653,7 @@ class DsMobileChatModalComponent {
12625
12653
  .then(() => {
12626
12654
  this.isKeyboardVisible = false;
12627
12655
  })
12628
- .catch(e => console.log('[ChatModal] Keyboard.hide() not available:', e));
12656
+ .catch((e) => console.log('[ChatModal] Keyboard.hide() not available:', e));
12629
12657
  return; // Exit early, don't toggle timestamp
12630
12658
  }
12631
12659
  // Keyboard is hidden, proceed with timestamp toggle
@@ -12634,7 +12662,7 @@ class DsMobileChatModalComponent {
12634
12662
  clearTimeout(this.timestampTimeout);
12635
12663
  }
12636
12664
  // Toggle timestamp - if clicking same message, hide it; otherwise show new one
12637
- this.selectedMessageId.update(current => current === messageId ? null : messageId);
12665
+ this.selectedMessageId.update((current) => current === messageId ? null : messageId);
12638
12666
  // Auto-hide after 3 seconds if showing
12639
12667
  if (this.selectedMessageId() === messageId) {
12640
12668
  this.timestampTimeout = setTimeout(() => {
@@ -12649,7 +12677,7 @@ class DsMobileChatModalComponent {
12649
12677
  return date.toLocaleTimeString('da-DK', {
12650
12678
  hour: '2-digit',
12651
12679
  minute: '2-digit',
12652
- hour12: false
12680
+ hour12: false,
12653
12681
  });
12654
12682
  }
12655
12683
  /**
@@ -12672,11 +12700,12 @@ class DsMobileChatModalComponent {
12672
12700
  // 1. It's the first message
12673
12701
  // 2. More than threshold minutes have passed since last message
12674
12702
  // 3. Date changed (new day)
12675
- if (!currentGroup || this.shouldStartNewGroup(currentGroup.timestamp, messageDate, thresholdMinutes)) {
12703
+ if (!currentGroup ||
12704
+ this.shouldStartNewGroup(currentGroup.timestamp, messageDate, thresholdMinutes)) {
12676
12705
  currentGroup = {
12677
12706
  timestamp: messageDate,
12678
12707
  displayTimestamp: this.formatGroupTimestamp(messageDate),
12679
- messages: []
12708
+ messages: [],
12680
12709
  };
12681
12710
  groups.push(currentGroup);
12682
12711
  }
@@ -12710,7 +12739,7 @@ class DsMobileChatModalComponent {
12710
12739
  const timeStr = date.toLocaleTimeString('da-DK', {
12711
12740
  hour: '2-digit',
12712
12741
  minute: '2-digit',
12713
- hour12: false
12742
+ hour12: false,
12714
12743
  });
12715
12744
  // Today: "14:34"
12716
12745
  if (messageDate.getTime() === today.getTime()) {
@@ -12723,12 +12752,12 @@ class DsMobileChatModalComponent {
12723
12752
  // This week: "Mandag, 14:34"
12724
12753
  const daysAgo = Math.floor((today.getTime() - messageDate.getTime()) / (1000 * 60 * 60 * 24));
12725
12754
  if (daysAgo < 7) {
12726
- return date.toLocaleDateString('da-DK', { weekday: 'long' }) + `, ${timeStr}`;
12755
+ return (date.toLocaleDateString('da-DK', { weekday: 'long' }) + `, ${timeStr}`);
12727
12756
  }
12728
12757
  // Older: "15. jan, 14:34" or "20. dec. 2024, 14:34" if different year
12729
12758
  const dateFormat = {
12730
12759
  month: 'short',
12731
- day: 'numeric'
12760
+ day: 'numeric',
12732
12761
  };
12733
12762
  if (date.getFullYear() !== now.getFullYear()) {
12734
12763
  dateFormat.year = 'numeric';
@@ -12741,7 +12770,7 @@ class DsMobileChatModalComponent {
12741
12770
  * and calculates cluster positions for border radius styling
12742
12771
  */
12743
12772
  addDisplayMetadata(groups) {
12744
- return groups.map(group => {
12773
+ return groups.map((group) => {
12745
12774
  const messagesWithDisplay = [];
12746
12775
  for (let i = 0; i < group.messages.length; i++) {
12747
12776
  const currentMsg = group.messages[i];
@@ -12770,12 +12799,12 @@ class DsMobileChatModalComponent {
12770
12799
  messagesWithDisplay.push({
12771
12800
  ...currentMsg,
12772
12801
  showAvatar,
12773
- clusterPosition
12802
+ clusterPosition,
12774
12803
  });
12775
12804
  }
12776
12805
  return {
12777
12806
  ...group,
12778
- messages: messagesWithDisplay
12807
+ messages: messagesWithDisplay,
12779
12808
  };
12780
12809
  });
12781
12810
  }
@@ -12789,8 +12818,8 @@ class DsMobileChatModalComponent {
12789
12818
  [hasFixedBottom]="true"
12790
12819
  [enableKeyboardHandling]="true"
12791
12820
  (keyboardWillShow)="handleKeyboardShow($event)"
12792
- closeButtonLabel="Luk chat">
12793
-
12821
+ closeButtonLabel="Luk chat"
12822
+ >
12794
12823
  <!-- Header Avatar -->
12795
12824
  <ds-avatar-with-badge
12796
12825
  header-leading
@@ -12815,94 +12844,109 @@ class DsMobileChatModalComponent {
12815
12844
  <div class="chat-avatar-name">
12816
12845
  {{ participant().name }}
12817
12846
  @if (participant().verified) {
12818
- <ds-icon name="remixCheckboxCircleFill" size="24px" [style.color]="'var(--color-primary-base)'"></ds-icon>
12847
+ <ds-icon
12848
+ name="remixCheckboxCircleFill"
12849
+ size="24px"
12850
+ [style.color]="'var(--color-primary-base)'"
12851
+ ></ds-icon>
12819
12852
  }
12820
12853
  </div>
12821
12854
  @if (participant().role) {
12822
- <div class="chat-avatar-role">{{ participant().role }}</div>
12823
- }
12824
- @if (participant().lastActive) {
12825
- <div class="chat-avatar-meta">{{ participant().lastActive }}</div>
12855
+ <div class="chat-avatar-role">{{ participant().role }}</div>
12856
+ } @if (participant().lastActive) {
12857
+ <div class="chat-avatar-meta">{{ participant().lastActive }}</div>
12826
12858
  }
12827
12859
  </div>
12828
12860
  </div>
12829
12861
 
12830
12862
  <div class="messages-list">
12831
12863
  @if (messages().length === 0) {
12832
- <!-- Empty State - Timestamp and System Message -->
12833
- <div class="timestamp-header">
12834
- <span class="timestamp-text">{{ getInitialTimestamp() }}</span>
12835
- </div>
12836
-
12837
- <ds-mobile-system-message-banner
12838
- [message]="participant().name + ' har overtaget din henvendelse og vil kontakte dig snart.'"
12839
- [afterTimestamp]="true">
12840
- </ds-mobile-system-message-banner>
12841
- } @else {
12842
- @for (group of messagesWithDisplay(); track group.timestamp) {
12843
- <!-- Timestamp Header -->
12844
- <div class="timestamp-header">
12845
- <span class="timestamp-text">{{ group.displayTimestamp }}</span>
12846
- </div>
12847
-
12848
- <!-- System message example (shown after first timestamp) -->
12849
- @if ($first) {
12850
- <ds-mobile-system-message-banner
12851
- [message]="participant().name + ' har overtaget din henvendelse og vil kontakte dig snart.'"
12852
- [afterTimestamp]="true">
12853
- </ds-mobile-system-message-banner>
12854
- }
12855
-
12856
- @for (message of group.messages; track message.id) {
12857
- <!-- Only show bubble if has content -->
12858
- @if (message.content.trim()) {
12859
- <ds-mobile-message-bubble
12860
- [content]="message.content"
12861
- [isOwnMessage]="message.isOwnMessage"
12862
- [timestamp]="formatMessageTimestamp(message.timestamp)"
12863
- [showTimestamp]="selectedMessageId() === message.id"
12864
- [avatarInitials]="message.avatarInitials || ''"
12865
- [avatarType]="message.avatarType || 'initials'"
12866
- [avatarSrc]="message.avatarSrc || ''"
12867
- [showAvatar]="message.showAvatar"
12868
- [clusterPosition]="message.clusterPosition"
12869
- [attachments]="message.attachments"
12870
- [clickable]="true"
12871
- [isNewMessage]="message.isNewMessage || false"
12872
- (messageClick)="handleMessageClick(message.id)"
12873
- (attachmentClick)="handleAttachmentClick($event)"
12874
- (longPress)="handleMessageLongPress(message)">
12875
- </ds-mobile-message-bubble>
12876
- }
12877
-
12878
- <!-- File attachments displayed below message bubble -->
12879
- @if (message.fileAttachments && message.fileAttachments.length > 0) {
12880
- <div class="message-file-attachments" [class.own-message]="message.isOwnMessage">
12881
- @for (fileAttachment of message.fileAttachments; track fileAttachment.id) {
12882
- <!-- Show inline image preview for image attachments -->
12883
- @if (fileAttachment.type === 'image') {
12884
- <div class="message-image-attachment" (click)="handleImageClick(fileAttachment, message)">
12885
- <img
12886
- [src]="fileAttachment.src"
12887
- [alt]="fileAttachment.name || 'Image'"
12888
- class="inline-image">
12889
- </div>
12890
- } @else {
12891
- <!-- Show file card for non-image attachments -->
12892
- <ds-mobile-card-inline-file
12893
- [fileName]="fileAttachment.name || 'Unknown file'"
12894
- [fileSize]="fileAttachment.size || ''"
12895
- [variant]="getFileVariant(fileAttachment.type)"
12896
- [layout]="'compact'"
12897
- (fileClick)="handleFileAttachmentClick(fileAttachment)">
12898
- </ds-mobile-card-inline-file>
12899
- }
12900
- }
12901
- </div>
12902
- }
12903
- }
12904
- }
12864
+ <!-- Empty State - Timestamp and System Message -->
12865
+ <div class="timestamp-header">
12866
+ <span class="timestamp-text">{{ getInitialTimestamp() }}</span>
12867
+ </div>
12868
+
12869
+ <ds-mobile-system-message-banner
12870
+ [message]="
12871
+ participant().name +
12872
+ ' har overtaget din henvendelse og vil kontakte dig snart.'
12873
+ "
12874
+ [afterTimestamp]="true"
12875
+ >
12876
+ </ds-mobile-system-message-banner>
12877
+ } @else { @for (group of messagesWithDisplay(); track group.timestamp)
12878
+ {
12879
+ <!-- Timestamp Header -->
12880
+ <div class="timestamp-header">
12881
+ <span class="timestamp-text">{{ group.displayTimestamp }}</span>
12882
+ </div>
12883
+
12884
+ <!-- System message example (shown after first timestamp) -->
12885
+ @if ($first) {
12886
+ <ds-mobile-system-message-banner
12887
+ [message]="
12888
+ participant().name +
12889
+ ' har overtaget din henvendelse og vil kontakte dig snart.'
12890
+ "
12891
+ [afterTimestamp]="true"
12892
+ >
12893
+ </ds-mobile-system-message-banner>
12894
+ } @for (message of group.messages; track message.id) {
12895
+ <!-- Only show bubble if has content -->
12896
+ @if (message.content.trim()) {
12897
+ <ds-mobile-message-bubble
12898
+ [content]="message.content"
12899
+ [isOwnMessage]="message.isOwnMessage"
12900
+ [timestamp]="formatMessageTimestamp(message.timestamp)"
12901
+ [showTimestamp]="selectedMessageId() === message.id"
12902
+ [avatarInitials]="message.avatarInitials || ''"
12903
+ [avatarType]="message.avatarType || 'initials'"
12904
+ [avatarSrc]="message.avatarSrc || ''"
12905
+ [showAvatar]="message.showAvatar"
12906
+ [clusterPosition]="message.clusterPosition"
12907
+ [attachments]="message.attachments"
12908
+ [clickable]="true"
12909
+ [isNewMessage]="message.isNewMessage || false"
12910
+ (messageClick)="handleMessageClick(message.id)"
12911
+ (attachmentClick)="handleAttachmentClick($event)"
12912
+ (longPress)="handleMessageLongPress(message)"
12913
+ >
12914
+ </ds-mobile-message-bubble>
12905
12915
  }
12916
+
12917
+ <!-- File attachments displayed below message bubble -->
12918
+ @if (message.fileAttachments && message.fileAttachments.length > 0) {
12919
+ <div
12920
+ class="message-file-attachments"
12921
+ [class.own-message]="message.isOwnMessage"
12922
+ >
12923
+ @for (fileAttachment of message.fileAttachments; track
12924
+ fileAttachment.id) {
12925
+ <!-- Show inline image preview for image attachments -->
12926
+ @if (fileAttachment.type === 'image') {
12927
+ <div
12928
+ class="message-image-attachment"
12929
+ (click)="handleImageClick(fileAttachment, message)"
12930
+ >
12931
+ <img
12932
+ [src]="fileAttachment.src"
12933
+ [alt]="fileAttachment.name || 'Image'"
12934
+ class="inline-image"
12935
+ />
12936
+ </div>
12937
+ } @else {
12938
+ <!-- Show file card for non-image attachments -->
12939
+ <ds-mobile-card-inline-file
12940
+ [fileName]="fileAttachment.name || 'Unknown file'"
12941
+ [fileSize]="fileAttachment.size || ''"
12942
+ [variant]="getFileVariant(fileAttachment.type)"
12943
+ [layout]="'compact'"
12944
+ (fileClick)="handleFileAttachmentClick(fileAttachment)"
12945
+ >
12946
+ </ds-mobile-card-inline-file>
12947
+ } }
12948
+ </div>
12949
+ } } } }
12906
12950
  </div>
12907
12951
  </div>
12908
12952
 
@@ -12917,11 +12961,12 @@ class DsMobileChatModalComponent {
12917
12961
  [showAttachmentButton]="true"
12918
12962
  (messageSent)="handleMessageSent($event)"
12919
12963
  (attachmentClicked)="handleComposerAttachmentClick()"
12920
- (attachmentsChanged)="handleAttachmentsChanged()">
12964
+ (attachmentsChanged)="handleAttachmentsChanged()"
12965
+ >
12921
12966
  </ds-mobile-message-composer>
12922
12967
  </div>
12923
12968
  </ds-mobile-modal-base>
12924
- `, 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-sm);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}.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}.chat-messages-container{display:flex;flex-direction:column;width:100%}.chat-avatar-section{display:flex;flex-direction:column;align-items:center;gap:12px;padding:48px 20px 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 20px 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}\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: DsMobileMessageComposerComponent, selector: "ds-mobile-message-composer", inputs: ["avatarInitials", "avatarType", "avatarSrc", "placeholder", "sendButtonLabel", "attachmentButtonLabel", "showAttachmentButton", "editIndicatorText", "replyIndicatorText", "enableMentions", "mentionUsers", "autoFocus"], outputs: ["messageSent", "editCancelled", "replyCancelled", "mentionSelected", "attachmentClicked", "attachmentsChanged"] }, { kind: "component", type: DsMobileMessageBubbleComponent, selector: "ds-mobile-message-bubble", inputs: ["content", "isOwnMessage", "senderName", "timestamp", "showTimestamp", "avatarInitials", "avatarType", "avatarSrc", "showAvatar", "clusterPosition", "attachments", "clickable", "isNewMessage"], outputs: ["attachmentClick", "longPress", "messageClick"] }, { kind: "component", type: DsMobileModalBaseComponent, selector: "ds-mobile-modal-base", inputs: ["showHeader"] }, { kind: "component", type: DsMobileCardInlineFileComponent, selector: "ds-mobile-card-inline-file", inputs: ["fileName", "fileSize", "variant", "layout"], 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"] }] });
12969
+ `, 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-sm);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}.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}.chat-messages-container{display:flex;flex-direction:column;width:100%}.chat-avatar-section{display:flex;flex-direction:column;align-items:center;gap:12px;padding:48px 20px 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 20px 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}\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: DsMobileMessageComposerComponent, selector: "ds-mobile-message-composer", inputs: ["avatarInitials", "avatarType", "avatarSrc", "placeholder", "sendButtonLabel", "attachmentButtonLabel", "showAttachmentButton", "editIndicatorText", "replyIndicatorText", "enableMentions", "mentionUsers", "autoFocus"], outputs: ["messageSent", "editCancelled", "replyCancelled", "mentionSelected", "attachmentClicked", "attachmentsChanged"] }, { kind: "component", type: DsMobileMessageBubbleComponent, selector: "ds-mobile-message-bubble", inputs: ["content", "isOwnMessage", "senderName", "timestamp", "showTimestamp", "avatarInitials", "avatarType", "avatarSrc", "showAvatar", "clusterPosition", "attachments", "clickable", "isNewMessage"], outputs: ["attachmentClick", "longPress", "messageClick"] }, { kind: "component", type: DsMobileModalBaseComponent, selector: "ds-mobile-modal-base", inputs: ["showHeader"] }, { 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"] }] });
12925
12970
  }
12926
12971
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsMobileChatModalComponent, decorators: [{
12927
12972
  type: Component,
@@ -12933,8 +12978,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
12933
12978
  DsMobileModalBaseComponent,
12934
12979
  DsMobileCardInlineFileComponent,
12935
12980
  DsMobileSystemMessageBannerComponent,
12936
- DsMobileEmptyStateComponent,
12937
- DsIconComponent
12981
+ DsIconComponent,
12938
12982
  ], schemas: [CUSTOM_ELEMENTS_SCHEMA], template: `
12939
12983
  <ds-mobile-modal-base
12940
12984
  [loading]="loading"
@@ -12944,8 +12988,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
12944
12988
  [hasFixedBottom]="true"
12945
12989
  [enableKeyboardHandling]="true"
12946
12990
  (keyboardWillShow)="handleKeyboardShow($event)"
12947
- closeButtonLabel="Luk chat">
12948
-
12991
+ closeButtonLabel="Luk chat"
12992
+ >
12949
12993
  <!-- Header Avatar -->
12950
12994
  <ds-avatar-with-badge
12951
12995
  header-leading
@@ -12970,94 +13014,109 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
12970
13014
  <div class="chat-avatar-name">
12971
13015
  {{ participant().name }}
12972
13016
  @if (participant().verified) {
12973
- <ds-icon name="remixCheckboxCircleFill" size="24px" [style.color]="'var(--color-primary-base)'"></ds-icon>
13017
+ <ds-icon
13018
+ name="remixCheckboxCircleFill"
13019
+ size="24px"
13020
+ [style.color]="'var(--color-primary-base)'"
13021
+ ></ds-icon>
12974
13022
  }
12975
13023
  </div>
12976
13024
  @if (participant().role) {
12977
- <div class="chat-avatar-role">{{ participant().role }}</div>
12978
- }
12979
- @if (participant().lastActive) {
12980
- <div class="chat-avatar-meta">{{ participant().lastActive }}</div>
13025
+ <div class="chat-avatar-role">{{ participant().role }}</div>
13026
+ } @if (participant().lastActive) {
13027
+ <div class="chat-avatar-meta">{{ participant().lastActive }}</div>
12981
13028
  }
12982
13029
  </div>
12983
13030
  </div>
12984
13031
 
12985
13032
  <div class="messages-list">
12986
13033
  @if (messages().length === 0) {
12987
- <!-- Empty State - Timestamp and System Message -->
12988
- <div class="timestamp-header">
12989
- <span class="timestamp-text">{{ getInitialTimestamp() }}</span>
12990
- </div>
12991
-
12992
- <ds-mobile-system-message-banner
12993
- [message]="participant().name + ' har overtaget din henvendelse og vil kontakte dig snart.'"
12994
- [afterTimestamp]="true">
12995
- </ds-mobile-system-message-banner>
12996
- } @else {
12997
- @for (group of messagesWithDisplay(); track group.timestamp) {
12998
- <!-- Timestamp Header -->
12999
- <div class="timestamp-header">
13000
- <span class="timestamp-text">{{ group.displayTimestamp }}</span>
13001
- </div>
13002
-
13003
- <!-- System message example (shown after first timestamp) -->
13004
- @if ($first) {
13005
- <ds-mobile-system-message-banner
13006
- [message]="participant().name + ' har overtaget din henvendelse og vil kontakte dig snart.'"
13007
- [afterTimestamp]="true">
13008
- </ds-mobile-system-message-banner>
13009
- }
13010
-
13011
- @for (message of group.messages; track message.id) {
13012
- <!-- Only show bubble if has content -->
13013
- @if (message.content.trim()) {
13014
- <ds-mobile-message-bubble
13015
- [content]="message.content"
13016
- [isOwnMessage]="message.isOwnMessage"
13017
- [timestamp]="formatMessageTimestamp(message.timestamp)"
13018
- [showTimestamp]="selectedMessageId() === message.id"
13019
- [avatarInitials]="message.avatarInitials || ''"
13020
- [avatarType]="message.avatarType || 'initials'"
13021
- [avatarSrc]="message.avatarSrc || ''"
13022
- [showAvatar]="message.showAvatar"
13023
- [clusterPosition]="message.clusterPosition"
13024
- [attachments]="message.attachments"
13025
- [clickable]="true"
13026
- [isNewMessage]="message.isNewMessage || false"
13027
- (messageClick)="handleMessageClick(message.id)"
13028
- (attachmentClick)="handleAttachmentClick($event)"
13029
- (longPress)="handleMessageLongPress(message)">
13030
- </ds-mobile-message-bubble>
13031
- }
13032
-
13033
- <!-- File attachments displayed below message bubble -->
13034
- @if (message.fileAttachments && message.fileAttachments.length > 0) {
13035
- <div class="message-file-attachments" [class.own-message]="message.isOwnMessage">
13036
- @for (fileAttachment of message.fileAttachments; track fileAttachment.id) {
13037
- <!-- Show inline image preview for image attachments -->
13038
- @if (fileAttachment.type === 'image') {
13039
- <div class="message-image-attachment" (click)="handleImageClick(fileAttachment, message)">
13040
- <img
13041
- [src]="fileAttachment.src"
13042
- [alt]="fileAttachment.name || 'Image'"
13043
- class="inline-image">
13044
- </div>
13045
- } @else {
13046
- <!-- Show file card for non-image attachments -->
13047
- <ds-mobile-card-inline-file
13048
- [fileName]="fileAttachment.name || 'Unknown file'"
13049
- [fileSize]="fileAttachment.size || ''"
13050
- [variant]="getFileVariant(fileAttachment.type)"
13051
- [layout]="'compact'"
13052
- (fileClick)="handleFileAttachmentClick(fileAttachment)">
13053
- </ds-mobile-card-inline-file>
13054
- }
13055
- }
13056
- </div>
13057
- }
13058
- }
13059
- }
13034
+ <!-- Empty State - Timestamp and System Message -->
13035
+ <div class="timestamp-header">
13036
+ <span class="timestamp-text">{{ getInitialTimestamp() }}</span>
13037
+ </div>
13038
+
13039
+ <ds-mobile-system-message-banner
13040
+ [message]="
13041
+ participant().name +
13042
+ ' har overtaget din henvendelse og vil kontakte dig snart.'
13043
+ "
13044
+ [afterTimestamp]="true"
13045
+ >
13046
+ </ds-mobile-system-message-banner>
13047
+ } @else { @for (group of messagesWithDisplay(); track group.timestamp)
13048
+ {
13049
+ <!-- Timestamp Header -->
13050
+ <div class="timestamp-header">
13051
+ <span class="timestamp-text">{{ group.displayTimestamp }}</span>
13052
+ </div>
13053
+
13054
+ <!-- System message example (shown after first timestamp) -->
13055
+ @if ($first) {
13056
+ <ds-mobile-system-message-banner
13057
+ [message]="
13058
+ participant().name +
13059
+ ' har overtaget din henvendelse og vil kontakte dig snart.'
13060
+ "
13061
+ [afterTimestamp]="true"
13062
+ >
13063
+ </ds-mobile-system-message-banner>
13064
+ } @for (message of group.messages; track message.id) {
13065
+ <!-- Only show bubble if has content -->
13066
+ @if (message.content.trim()) {
13067
+ <ds-mobile-message-bubble
13068
+ [content]="message.content"
13069
+ [isOwnMessage]="message.isOwnMessage"
13070
+ [timestamp]="formatMessageTimestamp(message.timestamp)"
13071
+ [showTimestamp]="selectedMessageId() === message.id"
13072
+ [avatarInitials]="message.avatarInitials || ''"
13073
+ [avatarType]="message.avatarType || 'initials'"
13074
+ [avatarSrc]="message.avatarSrc || ''"
13075
+ [showAvatar]="message.showAvatar"
13076
+ [clusterPosition]="message.clusterPosition"
13077
+ [attachments]="message.attachments"
13078
+ [clickable]="true"
13079
+ [isNewMessage]="message.isNewMessage || false"
13080
+ (messageClick)="handleMessageClick(message.id)"
13081
+ (attachmentClick)="handleAttachmentClick($event)"
13082
+ (longPress)="handleMessageLongPress(message)"
13083
+ >
13084
+ </ds-mobile-message-bubble>
13060
13085
  }
13086
+
13087
+ <!-- File attachments displayed below message bubble -->
13088
+ @if (message.fileAttachments && message.fileAttachments.length > 0) {
13089
+ <div
13090
+ class="message-file-attachments"
13091
+ [class.own-message]="message.isOwnMessage"
13092
+ >
13093
+ @for (fileAttachment of message.fileAttachments; track
13094
+ fileAttachment.id) {
13095
+ <!-- Show inline image preview for image attachments -->
13096
+ @if (fileAttachment.type === 'image') {
13097
+ <div
13098
+ class="message-image-attachment"
13099
+ (click)="handleImageClick(fileAttachment, message)"
13100
+ >
13101
+ <img
13102
+ [src]="fileAttachment.src"
13103
+ [alt]="fileAttachment.name || 'Image'"
13104
+ class="inline-image"
13105
+ />
13106
+ </div>
13107
+ } @else {
13108
+ <!-- Show file card for non-image attachments -->
13109
+ <ds-mobile-card-inline-file
13110
+ [fileName]="fileAttachment.name || 'Unknown file'"
13111
+ [fileSize]="fileAttachment.size || ''"
13112
+ [variant]="getFileVariant(fileAttachment.type)"
13113
+ [layout]="'compact'"
13114
+ (fileClick)="handleFileAttachmentClick(fileAttachment)"
13115
+ >
13116
+ </ds-mobile-card-inline-file>
13117
+ } }
13118
+ </div>
13119
+ } } } }
13061
13120
  </div>
13062
13121
  </div>
13063
13122
 
@@ -13072,7 +13131,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
13072
13131
  [showAttachmentButton]="true"
13073
13132
  (messageSent)="handleMessageSent($event)"
13074
13133
  (attachmentClicked)="handleComposerAttachmentClick()"
13075
- (attachmentsChanged)="handleAttachmentsChanged()">
13134
+ (attachmentsChanged)="handleAttachmentsChanged()"
13135
+ >
13076
13136
  </ds-mobile-message-composer>
13077
13137
  </div>
13078
13138
  </ds-mobile-modal-base>
@@ -13154,17 +13214,17 @@ class DsMobileChatModalService extends BaseModalService {
13154
13214
  * @returns Promise that resolves when the modal is presented
13155
13215
  */
13156
13216
  async open(chatData, options) {
13157
- console.log('[ChatModal] Opening with data:', chatData);
13217
+ // console.log('[ChatModal] Opening with data:', chatData);
13158
13218
  const modal = await this.createModal(DsMobileChatModalComponent, {
13159
13219
  chatData: chatData,
13160
13220
  loading: options?.loading ?? false,
13161
- error: options?.error
13221
+ error: options?.error,
13162
13222
  }, {
13163
13223
  keyboardClose: true, // Keep keyboard close behavior for this modal
13164
13224
  });
13165
- console.log('[ChatModal] Modal created, presenting...');
13225
+ // console.log('[ChatModal] Modal created, presenting...');
13166
13226
  await modal.present();
13167
- console.log('[ChatModal] Modal presented');
13227
+ // console.log('[ChatModal] Modal presented');
13168
13228
  }
13169
13229
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsMobileChatModalService, deps: [{ token: i1.ModalController }], target: i0.ɵɵFactoryTarget.Injectable });
13170
13230
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsMobileChatModalService, providedIn: 'root' });
@@ -13172,7 +13232,7 @@ class DsMobileChatModalService extends BaseModalService {
13172
13232
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsMobileChatModalService, decorators: [{
13173
13233
  type: Injectable,
13174
13234
  args: [{
13175
- providedIn: 'root'
13235
+ providedIn: 'root',
13176
13236
  }]
13177
13237
  }], ctorParameters: () => [{ type: i1.ModalController }] });
13178
13238
 
@@ -13695,17 +13755,17 @@ class DsMobileNewInquiryModalService extends BaseModalService {
13695
13755
  * @returns Promise that resolves when the modal is presented
13696
13756
  */
13697
13757
  async open(options) {
13698
- console.log('[NewInquiryModal] Opening modal with options:', options);
13758
+ // console.log('[NewInquiryModal] Opening modal with options:', options);
13699
13759
  const modal = await this.createModal(DsMobileNewInquiryModalComponent, {
13700
13760
  onSubmit: options?.onSubmit,
13701
13761
  loading: options?.loading ?? false,
13702
- error: options?.error
13762
+ error: options?.error,
13703
13763
  }, {
13704
13764
  keyboardClose: false, // Don't close on keyboard hide for this modal
13705
13765
  });
13706
- console.log('[NewInquiryModal] Modal created, presenting...');
13766
+ // console.log('[NewInquiryModal] Modal created, presenting...');
13707
13767
  await modal.present();
13708
- console.log('[NewInquiryModal] Modal presented');
13768
+ // console.log('[NewInquiryModal] Modal presented');
13709
13769
  }
13710
13770
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsMobileNewInquiryModalService, deps: [{ token: i1.ModalController }], target: i0.ɵɵFactoryTarget.Injectable });
13711
13771
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsMobileNewInquiryModalService, providedIn: 'root' });
@@ -13713,7 +13773,7 @@ class DsMobileNewInquiryModalService extends BaseModalService {
13713
13773
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsMobileNewInquiryModalService, decorators: [{
13714
13774
  type: Injectable,
13715
13775
  args: [{
13716
- providedIn: 'root'
13776
+ providedIn: 'root',
13717
13777
  }]
13718
13778
  }], ctorParameters: () => [{ type: i1.ModalController }] });
13719
13779
 
@@ -13944,7 +14004,7 @@ class DsMobileHandbookDetailModalComponent {
13944
14004
  variant: 'light-purple',
13945
14005
  iconName: 'remixFolder3Line',
13946
14006
  itemCount: 0,
13947
- items: []
14007
+ items: [],
13948
14008
  }, ...(ngDevMode ? [{ debugName: "handbook" }] : []));
13949
14009
  ngOnInit() {
13950
14010
  // Initialize handbook data from input
@@ -13965,41 +14025,27 @@ class DsMobileHandbookDetailModalComponent {
13965
14025
  const hasImages = item.images && item.images.length > 0;
13966
14026
  const hasContacts = item.contacts && item.contacts.length > 0;
13967
14027
  const hasAttachments = item.attachments && item.attachments.length > 0;
13968
- // Case 1: Only one type of content - keep as is
13969
- const contentTypeCount = [hasImages, hasContacts, hasAttachments].filter(Boolean).length;
13970
- if (contentTypeCount <= 1) {
13971
- return [item];
13972
- }
13973
- // Case 2: Has images + contacts (allowed together) but no attachments
13974
- if (hasImages && hasContacts && !hasAttachments) {
13975
- return [item];
13976
- }
13977
- // Case 3: Violates rules - need to split
13978
- // First item: Text + Images (if present)
13979
- if (hasImages) {
14028
+ const hasContent = hasContacts || hasAttachments;
14029
+ // Case 1: Images AND other content -> Split Pictures from (Contacts + Attachments)
14030
+ if (hasImages && hasContent) {
14031
+ // Part 1: Images
13980
14032
  displayItems.push({
13981
14033
  title: item.title,
13982
14034
  description: item.description,
13983
- images: item.images
13984
- });
13985
- }
13986
- // Second item: Text + Contacts (if present and no images shown yet)
13987
- if (hasContacts) {
13988
- displayItems.push({
13989
- title: item.title,
13990
- description: hasImages ? undefined : item.description, // Only show description if not shown before
13991
- contacts: item.contacts
14035
+ images: item.images,
13992
14036
  });
13993
- }
13994
- // Third item: Text + Attachments (if present)
13995
- if (hasAttachments) {
14037
+ // Part 2: Contacts + Attachments
13996
14038
  displayItems.push({
13997
- title: item.title,
13998
- description: (!hasImages && !hasContacts) ? item.description : undefined, // Only show description if not shown before
13999
- attachments: item.attachments
14039
+ title: '', // No title for the continuation
14040
+ description: undefined,
14041
+ contacts: item.contacts,
14042
+ attachments: item.attachments,
14000
14043
  });
14044
+ return displayItems;
14001
14045
  }
14002
- return displayItems;
14046
+ // Case 2: No splitting needed (Images only, or No Images)
14047
+ // This allows Contacts and Attachments to coexist in one item
14048
+ return [item];
14003
14049
  }
14004
14050
  /**
14005
14051
  * Get all display items with enforced content structure rules applied
@@ -14025,7 +14071,7 @@ class DsMobileHandbookDetailModalComponent {
14025
14071
  */
14026
14072
  handleAttachmentClick(attachment) {
14027
14073
  console.log('Attachment clicked:', attachment);
14028
- // Implement attachment action (e.g., open file viewer, download, etc.)
14074
+ // Attachment action is now handled by DsMobileCardInlineFileComponent via fileUrl input
14029
14075
  }
14030
14076
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsMobileHandbookDetailModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
14031
14077
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: DsMobileHandbookDetailModalComponent, isStandalone: true, selector: "ds-mobile-handbook-detail-modal", inputs: { handbookData: "handbookData", loading: "loading", error: "error" }, ngImport: i0, template: `
@@ -14034,88 +14080,90 @@ class DsMobileHandbookDetailModalComponent {
14034
14080
  [error]="error"
14035
14081
  [headerTitle]="handbook().title"
14036
14082
  [headerMeta]="handbook().itemCount + ' emner'"
14037
- closeButtonLabel="Luk">
14038
-
14083
+ closeButtonLabel="Luk"
14084
+ >
14039
14085
  <!-- Header Folder Icon -->
14040
14086
  <ds-mobile-handbook-folder-mini
14041
14087
  header-leading
14042
14088
  [variant]="handbook().variant"
14043
- [iconName]="handbook().iconName">
14089
+ [iconName]="handbook().iconName"
14090
+ >
14044
14091
  </ds-mobile-handbook-folder-mini>
14045
14092
 
14046
14093
  <!-- Content (main content slot) -->
14047
14094
  <div class="handbook-detail-container">
14048
- @if (handbook().items && handbook().items!.length > 0) {
14049
- @for (item of getDisplayItems(); track item.title + $index; let isLast = $last) {
14050
- <div class="handbook-item" [class.last-item]="isLast">
14051
- <div class="item-text-group">
14052
- <h2 class="item-title">{{ item.title }}</h2>
14053
-
14054
- @if (item.description) {
14055
- <p class="item-description">{{ item.description }}</p>
14056
- }
14057
- </div>
14058
-
14059
- <!-- Images -->
14060
- @if (item.images && item.images.length > 0) {
14061
- <ds-mobile-swiper [slideWidth]="item.images.length === 1 ? '100%' : '85%'" [gap]="16">
14062
- @for (image of item.images; track image) {
14063
- <div class="swiper-slide">
14064
- <img
14065
- [src]="image"
14066
- [alt]="item.title"
14067
- class="item-image"
14068
- />
14069
- </div>
14070
- }
14071
- </ds-mobile-swiper>
14072
- }
14073
-
14074
- <!-- Contacts -->
14075
- @if (item.contacts && item.contacts.length > 0) {
14076
- <div class="contacts-list">
14077
- @for (contact of item.contacts; track contact.name) {
14078
- <ds-mobile-card-inline-contact
14079
- [name]="contact.name"
14080
- [initials]="contact.initials"
14081
- [contactPerson]="contact.contactPerson || ''"
14082
- [phoneNumber]="contact.phoneNumber || ''"
14083
- [clickable]="true"
14084
- (contactClick)="handleContactClick(contact)">
14085
- </ds-mobile-card-inline-contact>
14086
- }
14087
- </div>
14088
- }
14089
-
14090
- <!-- Attachments -->
14091
- @if (item.attachments && item.attachments.length > 0) {
14092
- <div class="attachments-list">
14093
- @for (attachment of item.attachments; track attachment.name) {
14094
- <ds-mobile-card-inline-file
14095
- [fileName]="attachment.name"
14096
- [variant]="attachment.type === 'pdf' ? 'pdf' : 'doc'"
14097
- (fileClick)="handleAttachmentClick(attachment)">
14098
- </ds-mobile-card-inline-file>
14099
- }
14100
- </div>
14101
- }
14102
- </div>
14095
+ @if (handbook().items && handbook().items!.length > 0) { @for (item of
14096
+ getDisplayItems(); track item.title + $index; let isLast = $last) {
14097
+ <div class="handbook-item" [class.last-item]="isLast">
14098
+ <div class="item-text-group">
14099
+ @if (item.title) {
14100
+ <h2 class="item-title">{{ item.title }}</h2>
14101
+ } @if (item.description) {
14102
+ <p class="item-description" [innerHTML]="item.description"></p>
14103
14103
  }
14104
- } @else {
14105
- <!-- Empty State -->
14106
- <div class="handbook-empty-state">
14107
- <img
14108
- src="/Assets/Empty%20state-chat.png"
14109
- alt="No items yet"
14110
- class="empty-state-image"
14111
- />
14112
- <h3 class="empty-state-title">No items yet</h3>
14113
- <p class="empty-state-description">This folder is empty</p>
14114
14104
  </div>
14105
+
14106
+ <!-- Images -->
14107
+ @if (item.images && item.images.length > 0) {
14108
+ <ds-mobile-swiper
14109
+ [slideWidth]="item.images.length === 1 ? '100%' : '85%'"
14110
+ [gap]="16"
14111
+ >
14112
+ @for (image of item.images; track image) {
14113
+ <div class="swiper-slide">
14114
+ <img [src]="image" [alt]="item.title" class="item-image" />
14115
+ </div>
14116
+ }
14117
+ </ds-mobile-swiper>
14118
+ }
14119
+
14120
+ <!-- Contacts -->
14121
+ @if (item.contacts && item.contacts.length > 0) {
14122
+ <div class="contacts-list">
14123
+ @for (contact of item.contacts; track contact.name) {
14124
+ <ds-mobile-card-inline-contact
14125
+ [name]="contact.name"
14126
+ [initials]="contact.initials"
14127
+ [contactPerson]="contact.contactPerson || ''"
14128
+ [phoneNumber]="contact.phoneNumber || ''"
14129
+ [clickable]="true"
14130
+ (contactClick)="handleContactClick(contact)"
14131
+ >
14132
+ </ds-mobile-card-inline-contact>
14133
+ }
14134
+ </div>
14135
+ }
14136
+
14137
+ <!-- Attachments -->
14138
+ @if (item.attachments && item.attachments.length > 0) {
14139
+ <div class="attachments-list">
14140
+ @for (attachment of item.attachments; track attachment.name) {
14141
+ <ds-mobile-card-inline-file
14142
+ [fileName]="attachment.name"
14143
+ [variant]="attachment.type === 'pdf' ? 'pdf' : 'doc'"
14144
+ [fileUrl]="attachment.url"
14145
+ (fileClick)="handleAttachmentClick(attachment)"
14146
+ >
14147
+ </ds-mobile-card-inline-file>
14148
+ }
14149
+ </div>
14150
+ }
14151
+ </div>
14152
+ } } @else {
14153
+ <!-- Empty State -->
14154
+ <div class="handbook-empty-state">
14155
+ <img
14156
+ src="/Assets/Empty%20state-chat.png"
14157
+ alt="No items yet"
14158
+ class="empty-state-image"
14159
+ />
14160
+ <h3 class="empty-state-title">No items yet</h3>
14161
+ <p class="empty-state-description">This folder is empty</p>
14162
+ </div>
14115
14163
  }
14116
14164
  </div>
14117
14165
  </ds-mobile-modal-base>
14118
- `, isInline: true, styles: [".handbook-detail-container{display:flex;flex-direction:column;width:100%;flex:1}.handbook-item{width:100%;display:flex;flex-direction:column;gap:24px;padding:24px 20px;border-bottom:1px solid var(--border-color-default)}.handbook-item.last-item{border-bottom:none}.item-text-group{display:flex;flex-direction:column;gap:8px}.item-title{font-family:Brockmann,sans-serif;font-size:16px;font-weight:600;line-height:24px;color:var(--color-text-primary, #1a1a1a);margin:0}.item-description{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);line-height:20px;color:var(--color-text-primary, #1a1a1a);margin:0}.item-image{width:100%;max-width:100%;height:280px;-o-object-fit:cover;object-fit:cover;border-radius:12px;display:block}.contacts-list,.attachments-list{display:flex;flex-direction:column;gap:8px}.handbook-empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:60px 20px;text-align:center}.empty-state-image{width:96px;height:96px}.empty-state-title{font-family:Brockmann,sans-serif;font-size:var(--font-size-base);font-weight:600;line-height:1.3;color:var(--color-text-primary, #1a1a1a)}.empty-state-description{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:400;line-height:1.4;color:var(--color-text-secondary, #737373)}@supports (padding: env(safe-area-inset-bottom)){.handbook-detail-container{padding-bottom:calc(20px + env(safe-area-inset-bottom))}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: DsMobileHandbookFolderMiniComponent, selector: "ds-mobile-handbook-folder-mini", inputs: ["variant", "iconName"] }, { kind: "component", type: DsMobileCardInlineFileComponent, selector: "ds-mobile-card-inline-file", inputs: ["fileName", "fileSize", "variant", "layout"], outputs: ["fileClick"] }, { kind: "component", type: DsMobileCardInlineContactComponent, selector: "ds-mobile-card-inline-contact", inputs: ["name", "initials", "contactPerson", "phoneNumber", "layout", "clickable", "showChevron"], outputs: ["contactClick"] }, { kind: "component", type: DsMobileSwiperComponent, selector: "ds-mobile-swiper", inputs: ["slideWidth", "gap"] }, { kind: "component", type: DsMobileModalBaseComponent, selector: "ds-mobile-modal-base", inputs: ["showHeader"] }] });
14166
+ `, isInline: true, styles: [".handbook-detail-container{display:flex;flex-direction:column;width:100%;flex:1}.handbook-item{width:100%;display:flex;flex-direction:column;gap:24px;padding:24px 20px;border-bottom:1px solid var(--border-color-default)}.handbook-item.last-item{border-bottom:none}.item-text-group{display:flex;flex-direction:column;gap:8px}.item-title{font-family:Brockmann,sans-serif;font-size:16px;font-weight:600;line-height:24px;color:var(--color-text-primary, #1a1a1a);margin:0}.item-description{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);line-height:20px;color:var(--color-text-primary, #1a1a1a);margin:0}.item-image{width:100%;max-width:100%;height:280px;-o-object-fit:cover;object-fit:cover;border-radius:12px;display:block}.contacts-list,.attachments-list{display:flex;flex-direction:column;gap:8px}.handbook-empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:60px 20px;text-align:center}.empty-state-image{width:96px;height:96px}.empty-state-title{font-family:Brockmann,sans-serif;font-size:var(--font-size-base);font-weight:600;line-height:1.3;color:var(--color-text-primary, #1a1a1a)}.empty-state-description{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:400;line-height:1.4;color:var(--color-text-secondary, #737373)}@supports (padding: env(safe-area-inset-bottom)){.handbook-detail-container{padding-bottom:calc(20px + env(safe-area-inset-bottom))}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: DsMobileHandbookFolderMiniComponent, selector: "ds-mobile-handbook-folder-mini", inputs: ["variant", "iconName"] }, { kind: "component", type: DsMobileCardInlineFileComponent, selector: "ds-mobile-card-inline-file", inputs: ["fileName", "fileSize", "variant", "layout", "fileUrl"], outputs: ["fileClick"] }, { kind: "component", type: DsMobileCardInlineContactComponent, selector: "ds-mobile-card-inline-contact", inputs: ["name", "initials", "contactPerson", "phoneNumber", "layout", "clickable", "showChevron"], outputs: ["contactClick"] }, { kind: "component", type: DsMobileSwiperComponent, selector: "ds-mobile-swiper", inputs: ["slideWidth", "gap"] }, { kind: "component", type: DsMobileModalBaseComponent, selector: "ds-mobile-modal-base", inputs: ["showHeader"] }] });
14119
14167
  }
14120
14168
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsMobileHandbookDetailModalComponent, decorators: [{
14121
14169
  type: Component,
@@ -14125,91 +14173,93 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
14125
14173
  DsMobileCardInlineFileComponent,
14126
14174
  DsMobileCardInlineContactComponent,
14127
14175
  DsMobileSwiperComponent,
14128
- DsMobileModalBaseComponent
14176
+ DsMobileModalBaseComponent,
14129
14177
  ], schemas: [CUSTOM_ELEMENTS_SCHEMA], template: `
14130
14178
  <ds-mobile-modal-base
14131
14179
  [loading]="loading"
14132
14180
  [error]="error"
14133
14181
  [headerTitle]="handbook().title"
14134
14182
  [headerMeta]="handbook().itemCount + ' emner'"
14135
- closeButtonLabel="Luk">
14136
-
14183
+ closeButtonLabel="Luk"
14184
+ >
14137
14185
  <!-- Header Folder Icon -->
14138
14186
  <ds-mobile-handbook-folder-mini
14139
14187
  header-leading
14140
14188
  [variant]="handbook().variant"
14141
- [iconName]="handbook().iconName">
14189
+ [iconName]="handbook().iconName"
14190
+ >
14142
14191
  </ds-mobile-handbook-folder-mini>
14143
14192
 
14144
14193
  <!-- Content (main content slot) -->
14145
14194
  <div class="handbook-detail-container">
14146
- @if (handbook().items && handbook().items!.length > 0) {
14147
- @for (item of getDisplayItems(); track item.title + $index; let isLast = $last) {
14148
- <div class="handbook-item" [class.last-item]="isLast">
14149
- <div class="item-text-group">
14150
- <h2 class="item-title">{{ item.title }}</h2>
14151
-
14152
- @if (item.description) {
14153
- <p class="item-description">{{ item.description }}</p>
14154
- }
14155
- </div>
14156
-
14157
- <!-- Images -->
14158
- @if (item.images && item.images.length > 0) {
14159
- <ds-mobile-swiper [slideWidth]="item.images.length === 1 ? '100%' : '85%'" [gap]="16">
14160
- @for (image of item.images; track image) {
14161
- <div class="swiper-slide">
14162
- <img
14163
- [src]="image"
14164
- [alt]="item.title"
14165
- class="item-image"
14166
- />
14167
- </div>
14168
- }
14169
- </ds-mobile-swiper>
14170
- }
14171
-
14172
- <!-- Contacts -->
14173
- @if (item.contacts && item.contacts.length > 0) {
14174
- <div class="contacts-list">
14175
- @for (contact of item.contacts; track contact.name) {
14176
- <ds-mobile-card-inline-contact
14177
- [name]="contact.name"
14178
- [initials]="contact.initials"
14179
- [contactPerson]="contact.contactPerson || ''"
14180
- [phoneNumber]="contact.phoneNumber || ''"
14181
- [clickable]="true"
14182
- (contactClick)="handleContactClick(contact)">
14183
- </ds-mobile-card-inline-contact>
14184
- }
14185
- </div>
14186
- }
14187
-
14188
- <!-- Attachments -->
14189
- @if (item.attachments && item.attachments.length > 0) {
14190
- <div class="attachments-list">
14191
- @for (attachment of item.attachments; track attachment.name) {
14192
- <ds-mobile-card-inline-file
14193
- [fileName]="attachment.name"
14194
- [variant]="attachment.type === 'pdf' ? 'pdf' : 'doc'"
14195
- (fileClick)="handleAttachmentClick(attachment)">
14196
- </ds-mobile-card-inline-file>
14197
- }
14198
- </div>
14199
- }
14200
- </div>
14195
+ @if (handbook().items && handbook().items!.length > 0) { @for (item of
14196
+ getDisplayItems(); track item.title + $index; let isLast = $last) {
14197
+ <div class="handbook-item" [class.last-item]="isLast">
14198
+ <div class="item-text-group">
14199
+ @if (item.title) {
14200
+ <h2 class="item-title">{{ item.title }}</h2>
14201
+ } @if (item.description) {
14202
+ <p class="item-description" [innerHTML]="item.description"></p>
14201
14203
  }
14202
- } @else {
14203
- <!-- Empty State -->
14204
- <div class="handbook-empty-state">
14205
- <img
14206
- src="/Assets/Empty%20state-chat.png"
14207
- alt="No items yet"
14208
- class="empty-state-image"
14209
- />
14210
- <h3 class="empty-state-title">No items yet</h3>
14211
- <p class="empty-state-description">This folder is empty</p>
14212
14204
  </div>
14205
+
14206
+ <!-- Images -->
14207
+ @if (item.images && item.images.length > 0) {
14208
+ <ds-mobile-swiper
14209
+ [slideWidth]="item.images.length === 1 ? '100%' : '85%'"
14210
+ [gap]="16"
14211
+ >
14212
+ @for (image of item.images; track image) {
14213
+ <div class="swiper-slide">
14214
+ <img [src]="image" [alt]="item.title" class="item-image" />
14215
+ </div>
14216
+ }
14217
+ </ds-mobile-swiper>
14218
+ }
14219
+
14220
+ <!-- Contacts -->
14221
+ @if (item.contacts && item.contacts.length > 0) {
14222
+ <div class="contacts-list">
14223
+ @for (contact of item.contacts; track contact.name) {
14224
+ <ds-mobile-card-inline-contact
14225
+ [name]="contact.name"
14226
+ [initials]="contact.initials"
14227
+ [contactPerson]="contact.contactPerson || ''"
14228
+ [phoneNumber]="contact.phoneNumber || ''"
14229
+ [clickable]="true"
14230
+ (contactClick)="handleContactClick(contact)"
14231
+ >
14232
+ </ds-mobile-card-inline-contact>
14233
+ }
14234
+ </div>
14235
+ }
14236
+
14237
+ <!-- Attachments -->
14238
+ @if (item.attachments && item.attachments.length > 0) {
14239
+ <div class="attachments-list">
14240
+ @for (attachment of item.attachments; track attachment.name) {
14241
+ <ds-mobile-card-inline-file
14242
+ [fileName]="attachment.name"
14243
+ [variant]="attachment.type === 'pdf' ? 'pdf' : 'doc'"
14244
+ [fileUrl]="attachment.url"
14245
+ (fileClick)="handleAttachmentClick(attachment)"
14246
+ >
14247
+ </ds-mobile-card-inline-file>
14248
+ }
14249
+ </div>
14250
+ }
14251
+ </div>
14252
+ } } @else {
14253
+ <!-- Empty State -->
14254
+ <div class="handbook-empty-state">
14255
+ <img
14256
+ src="/Assets/Empty%20state-chat.png"
14257
+ alt="No items yet"
14258
+ class="empty-state-image"
14259
+ />
14260
+ <h3 class="empty-state-title">No items yet</h3>
14261
+ <p class="empty-state-description">This folder is empty</p>
14262
+ </div>
14213
14263
  }
14214
14264
  </div>
14215
14265
  </ds-mobile-modal-base>
@@ -14272,17 +14322,17 @@ class DsMobileHandbookDetailModalService extends BaseModalService {
14272
14322
  * @returns Promise that resolves when the modal is presented
14273
14323
  */
14274
14324
  async open(handbookData, options) {
14275
- console.log('[HandbookDetailModal] Opening with data:', handbookData);
14325
+ // console.log('[HandbookDetailModal] Opening with data:', handbookData);
14276
14326
  const modal = await this.createModal(DsMobileHandbookDetailModalComponent, {
14277
14327
  handbookData: handbookData,
14278
14328
  loading: options?.loading ?? false,
14279
- error: options?.error
14329
+ error: options?.error,
14280
14330
  }, {
14281
14331
  keyboardClose: true, // Keep keyboard close behavior for this modal
14282
14332
  });
14283
- console.log('[HandbookDetailModal] Modal created, presenting...');
14333
+ // console.log('[HandbookDetailModal] Modal created, presenting...');
14284
14334
  await modal.present();
14285
- console.log('[HandbookDetailModal] Modal presented');
14335
+ // console.log('[HandbookDetailModal] Modal presented');
14286
14336
  }
14287
14337
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsMobileHandbookDetailModalService, deps: [{ token: i1.ModalController }], target: i0.ɵɵFactoryTarget.Injectable });
14288
14338
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsMobileHandbookDetailModalService, providedIn: 'root' });
@@ -14290,7 +14340,7 @@ class DsMobileHandbookDetailModalService extends BaseModalService {
14290
14340
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsMobileHandbookDetailModalService, decorators: [{
14291
14341
  type: Injectable,
14292
14342
  args: [{
14293
- providedIn: 'root'
14343
+ providedIn: 'root',
14294
14344
  }]
14295
14345
  }], ctorParameters: () => [{ type: i1.ModalController }] });
14296
14346
 
@@ -14373,7 +14423,7 @@ class DsMobileHandbookFolderComponent {
14373
14423
  'salmon-orange': 'salmon-orange',
14374
14424
  'orange': 'orange',
14375
14425
  'lime-green': 'lime-green',
14376
- 'grey': 'grey'
14426
+ 'grey': 'grey',
14377
14427
  };
14378
14428
  const colorName = variantMap[this.variant] || 'light-purple';
14379
14429
  return `var(--color-${colorName}-${suffix})`;
@@ -14422,11 +14472,11 @@ class DsMobileHandbookFolderComponent {
14422
14472
  variant: this.variant,
14423
14473
  iconName: this.iconName,
14424
14474
  itemCount: this.itemCount,
14425
- items: this.items
14475
+ items: this.items,
14426
14476
  };
14427
14477
  await this.handbookModal.open(handbookData, {
14428
14478
  loading: this.loading,
14429
- error: this.error
14479
+ error: this.error,
14430
14480
  });
14431
14481
  }
14432
14482
  /**
@@ -14442,55 +14492,43 @@ class DsMobileHandbookFolderComponent {
14442
14492
  }
14443
14493
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsMobileHandbookFolderComponent, deps: [{ token: DsMobileHandbookDetailModalService }], target: i0.ɵɵFactoryTarget.Component });
14444
14494
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: DsMobileHandbookFolderComponent, isStandalone: true, selector: "ds-mobile-handbook-folder", inputs: { variant: "variant", iconName: "iconName", itemCount: "itemCount", label: "label", items: "items", loading: "loading", error: "error" }, host: { listeners: { "mouseenter": "open()", "mouseleave": "close()", "touchstart": "onTouchStart($event)", "touchend": "onTouchEnd()", "touchcancel": "onTouchCancel()", "click": "onClick()" } }, ngImport: i0, template: `
14445
- <div class="folder-container"
14446
- [class.open]="isOpen()">
14495
+ <div class="folder-container" [class.open]="isOpen()">
14447
14496
  <!-- Folder Tab SVG -->
14448
- <svg
14449
- class="folder-tab"
14450
- width="101"
14451
- height="24"
14452
- viewBox="0 0 101 24"
14453
- fill="none"
14454
- xmlns="http://www.w3.org/2000/svg">
14455
- <path
14456
- d="M100.037 23.9999L100.5 24L0 24.0001V10.7646C0 4.80853 4.91797 -0.0234985 11 -0.0196688L66.4213 -0.0322266C69.3519 -0.0115886 72.197 1.20548 74.2473 3.29947L90.6765 20.0951C93.1218 22.5925 96.5417 23.9999 100.037 23.9999Z"
14457
- [attr.fill]="getColorVar('strong')"/>
14497
+ <svg class="folder-tab" width="101" height="24" viewBox="0 0 101 24" fill="none" xmlns="http://www.w3.org/2000/svg">
14498
+ <path
14499
+ d="M100.037 23.9999L100.5 24L0 24.0001V10.7646C0 4.80853 4.91797 -0.0234985 11 -0.0196688L66.4213 -0.0322266C69.3519 -0.0115886 72.197 1.20548 74.2473 3.29947L90.6765 20.0951C93.1218 22.5925 96.5417 23.9999 100.037 23.9999Z"
14500
+ [attr.fill]="getColorVar('strong')"
14501
+ />
14458
14502
  </svg>
14459
-
14503
+
14460
14504
  <!-- Folder Back -->
14461
14505
  <div class="folder-back" [style.background-color]="getColorVar('strong')">
14462
14506
  <!-- Page Sheets -->
14463
14507
  @for (sheet of getPageSheets(); track $index) {
14464
- <div class="page-sheet"></div>
14508
+ <div class="page-sheet"></div>
14465
14509
  }
14466
-
14510
+
14467
14511
  <!-- Folder Front -->
14468
- <div
14469
- class="folder-front"
14470
- [style.--border-color]="getColorVar('strong')"
14471
- [style.background-color]="getColorVar('base')">
14512
+ <div class="folder-front" [style.--border-color]="getColorVar('strong')" [style.background-color]="getColorVar('base')">
14472
14513
  <!-- Icon (Centered) -->
14473
14514
  <div class="folder-icon">
14474
- <ds-icon
14475
- [name]="iconName"
14476
- [size]="'32px'"
14477
- [style.color]="'white'" />
14515
+ <ds-icon [name]="iconName" [size]="'32px'" [style.color]="'white'" />
14478
14516
  </div>
14479
14517
  </div>
14480
14518
  </div>
14481
14519
  </div>
14482
-
14520
+
14483
14521
  <!-- Label and Item Count -->
14484
14522
  <div class="folder-label-container">
14485
14523
  <div class="folder-label ui-sm-semiBold">{{ label }}</div>
14486
14524
  <div class="item-count ui-sm-regular" [style.color]="'var(--color-text-secondary, #6b7280)'">
14487
14525
  @if (loading) {
14488
- <span class="loading-indicator">Loading...</span>
14526
+ <span class="loading-indicator">Loading...</span>
14489
14527
  } @else if (error) {
14490
- <span class="error-indicator" [style.color]="'var(--color-destructive-base)'">Error</span>
14528
+ <span class="error-indicator" [style.color]="'var(--color-destructive-base)'">Error</span>
14491
14529
  } @else {
14492
- <span>{{ itemCount }}</span>
14493
- <span class="item-count-label">emner</span>
14530
+ <span>{{ itemCount }}</span>
14531
+ <span class="item-count-label">emner</span>
14494
14532
  }
14495
14533
  </div>
14496
14534
  </div>
@@ -14499,55 +14537,43 @@ class DsMobileHandbookFolderComponent {
14499
14537
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsMobileHandbookFolderComponent, decorators: [{
14500
14538
  type: Component,
14501
14539
  args: [{ selector: 'ds-mobile-handbook-folder', standalone: true, imports: [CommonModule, DsIconComponent], template: `
14502
- <div class="folder-container"
14503
- [class.open]="isOpen()">
14540
+ <div class="folder-container" [class.open]="isOpen()">
14504
14541
  <!-- Folder Tab SVG -->
14505
- <svg
14506
- class="folder-tab"
14507
- width="101"
14508
- height="24"
14509
- viewBox="0 0 101 24"
14510
- fill="none"
14511
- xmlns="http://www.w3.org/2000/svg">
14512
- <path
14513
- d="M100.037 23.9999L100.5 24L0 24.0001V10.7646C0 4.80853 4.91797 -0.0234985 11 -0.0196688L66.4213 -0.0322266C69.3519 -0.0115886 72.197 1.20548 74.2473 3.29947L90.6765 20.0951C93.1218 22.5925 96.5417 23.9999 100.037 23.9999Z"
14514
- [attr.fill]="getColorVar('strong')"/>
14542
+ <svg class="folder-tab" width="101" height="24" viewBox="0 0 101 24" fill="none" xmlns="http://www.w3.org/2000/svg">
14543
+ <path
14544
+ d="M100.037 23.9999L100.5 24L0 24.0001V10.7646C0 4.80853 4.91797 -0.0234985 11 -0.0196688L66.4213 -0.0322266C69.3519 -0.0115886 72.197 1.20548 74.2473 3.29947L90.6765 20.0951C93.1218 22.5925 96.5417 23.9999 100.037 23.9999Z"
14545
+ [attr.fill]="getColorVar('strong')"
14546
+ />
14515
14547
  </svg>
14516
-
14548
+
14517
14549
  <!-- Folder Back -->
14518
14550
  <div class="folder-back" [style.background-color]="getColorVar('strong')">
14519
14551
  <!-- Page Sheets -->
14520
14552
  @for (sheet of getPageSheets(); track $index) {
14521
- <div class="page-sheet"></div>
14553
+ <div class="page-sheet"></div>
14522
14554
  }
14523
-
14555
+
14524
14556
  <!-- Folder Front -->
14525
- <div
14526
- class="folder-front"
14527
- [style.--border-color]="getColorVar('strong')"
14528
- [style.background-color]="getColorVar('base')">
14557
+ <div class="folder-front" [style.--border-color]="getColorVar('strong')" [style.background-color]="getColorVar('base')">
14529
14558
  <!-- Icon (Centered) -->
14530
14559
  <div class="folder-icon">
14531
- <ds-icon
14532
- [name]="iconName"
14533
- [size]="'32px'"
14534
- [style.color]="'white'" />
14560
+ <ds-icon [name]="iconName" [size]="'32px'" [style.color]="'white'" />
14535
14561
  </div>
14536
14562
  </div>
14537
14563
  </div>
14538
14564
  </div>
14539
-
14565
+
14540
14566
  <!-- Label and Item Count -->
14541
14567
  <div class="folder-label-container">
14542
14568
  <div class="folder-label ui-sm-semiBold">{{ label }}</div>
14543
14569
  <div class="item-count ui-sm-regular" [style.color]="'var(--color-text-secondary, #6b7280)'">
14544
14570
  @if (loading) {
14545
- <span class="loading-indicator">Loading...</span>
14571
+ <span class="loading-indicator">Loading...</span>
14546
14572
  } @else if (error) {
14547
- <span class="error-indicator" [style.color]="'var(--color-destructive-base)'">Error</span>
14573
+ <span class="error-indicator" [style.color]="'var(--color-destructive-base)'">Error</span>
14548
14574
  } @else {
14549
- <span>{{ itemCount }}</span>
14550
- <span class="item-count-label">emner</span>
14575
+ <span>{{ itemCount }}</span>
14576
+ <span class="item-count-label">emner</span>
14551
14577
  }
14552
14578
  </div>
14553
14579
  </div>
@@ -15916,7 +15942,7 @@ class MobileCommunityPageComponent {
15916
15942
  </div>
15917
15943
  </ds-mobile-content>
15918
15944
  </ds-mobile-page-main>
15919
- `, isInline: true, styles: [".post-feed,.post-list-wrapper{display:flex;flex-direction:column}.pinned-posts-section{margin:-12px -12px 12px;padding:0 12px 12px;box-shadow:var(--box-shadow-sm);border-radius:16px;border:1px solid var(--border-color-default)}.clickable-image{cursor:pointer;transition:transform .2s ease,opacity .2s ease;border-radius:8px;display:block;width:100%;aspect-ratio:16/9;object-fit:cover}.clickable-image:active{transform:scale(.98);opacity:.9}.community-empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:60px 20px;text-align:center}.empty-state-image{width:96px;height:96px;margin-bottom:24px}ion-infinite-scroll{--color: var(--color-primary-surface)}ion-infinite-scroll-content{--color: var(--color-primary-surface)}ion-infinite-scroll-content::part(spinner){color:var(--color-primary-surface)}\n"], dependencies: [{ kind: "component", type: DsMobilePageMainComponent, selector: "ds-mobile-page-main", inputs: ["title", "headerTitle", "headerSubtitle", "avatarType", "avatarInitials", "avatarSrc", "avatarIconName", "showRefresh", "showCondensedHeader", "scrollThreshold", "headerFadeDistance", "profileMenuItems"], outputs: ["avatarClick", "profileActionSelected", "refresh", "scroll"] }, { kind: "component", type: DsMobileContentComponent, selector: "ds-mobile-content", inputs: ["layout"] }, { kind: "component", type: DsMobileInteractiveListItemPostComponent, selector: "ds-mobile-interactive-list-item-post", inputs: ["authorName", "authorRole", "timestamp", "avatarInitials", "avatarType", "avatarSrc", "avatarIconName", "showBadge", "variant", "clickable"], outputs: ["postClick", "commentClick", "longPress"] }, { kind: "component", type: DsMobilePostComposerComponent, selector: "ds-mobile-post-composer", inputs: ["avatarInitials", "avatarType", "avatarSrc", "avatarIconName", "placeholder", "buttonText"], outputs: ["composerClick"] }, { kind: "component", type: PostContentComponent, selector: "post-content" }, { kind: "component", type: PostTextComponent, selector: "post-text" }, { kind: "component", type: PostMediaComponent, selector: "post-media" }, { kind: "component", type: PostAttachmentsComponent, selector: "post-attachments" }, { kind: "component", type: PostActionsComponent, selector: "post-actions" }, { kind: "component", type: ActionLikeComponent, selector: "action-like", inputs: ["active", "count"], outputs: ["activeChange", "countChange", "likeClick"] }, { kind: "component", type: ActionCommentComponent, selector: "action-comment", inputs: ["count"], outputs: ["commentClick"] }, { kind: "component", type: DsMobileCardInlineFileComponent, selector: "ds-mobile-card-inline-file", inputs: ["fileName", "fileSize", "variant", "layout"], outputs: ["fileClick"] }, { kind: "component", type: DsIconComponent, selector: "ds-icon", inputs: ["name", "size", "color", "interactive"] }, { kind: "component", type: DsMobileInlinePhotoComponent, selector: "ds-mobile-inline-photo", inputs: ["images", "author", "maxVisible"], outputs: ["photoClick"] }, { kind: "component", type: IonInfiniteScroll, selector: "ion-infinite-scroll", inputs: ["disabled", "position", "threshold"] }, { kind: "component", type: IonInfiniteScrollContent, selector: "ion-infinite-scroll-content", inputs: ["loadingSpinner", "loadingText"] }] });
15945
+ `, isInline: true, styles: [".post-feed,.post-list-wrapper{display:flex;flex-direction:column}.pinned-posts-section{margin:-12px -12px 12px;padding:0 12px 12px;box-shadow:var(--box-shadow-sm);border-radius:16px;border:1px solid var(--border-color-default)}.clickable-image{cursor:pointer;transition:transform .2s ease,opacity .2s ease;border-radius:8px;display:block;width:100%;aspect-ratio:16/9;object-fit:cover}.clickable-image:active{transform:scale(.98);opacity:.9}.community-empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:60px 20px;text-align:center}.empty-state-image{width:96px;height:96px;margin-bottom:24px}ion-infinite-scroll{--color: var(--color-primary-surface)}ion-infinite-scroll-content{--color: var(--color-primary-surface)}ion-infinite-scroll-content::part(spinner){color:var(--color-primary-surface)}\n"], dependencies: [{ kind: "component", type: DsMobilePageMainComponent, selector: "ds-mobile-page-main", inputs: ["title", "headerTitle", "headerSubtitle", "avatarType", "avatarInitials", "avatarSrc", "avatarIconName", "showRefresh", "showCondensedHeader", "scrollThreshold", "headerFadeDistance", "profileMenuItems"], outputs: ["avatarClick", "profileActionSelected", "refresh", "scroll"] }, { kind: "component", type: DsMobileContentComponent, selector: "ds-mobile-content", inputs: ["layout"] }, { kind: "component", type: DsMobileInteractiveListItemPostComponent, selector: "ds-mobile-interactive-list-item-post", inputs: ["authorName", "authorRole", "timestamp", "avatarInitials", "avatarType", "avatarSrc", "avatarIconName", "showBadge", "variant", "clickable"], outputs: ["postClick", "commentClick", "longPress"] }, { kind: "component", type: DsMobilePostComposerComponent, selector: "ds-mobile-post-composer", inputs: ["avatarInitials", "avatarType", "avatarSrc", "avatarIconName", "placeholder", "buttonText"], outputs: ["composerClick"] }, { kind: "component", type: PostContentComponent, selector: "post-content" }, { kind: "component", type: PostTextComponent, selector: "post-text" }, { kind: "component", type: PostMediaComponent, selector: "post-media" }, { kind: "component", type: PostAttachmentsComponent, selector: "post-attachments" }, { kind: "component", type: PostActionsComponent, selector: "post-actions" }, { kind: "component", type: ActionLikeComponent, selector: "action-like", inputs: ["active", "count"], outputs: ["activeChange", "countChange", "likeClick"] }, { kind: "component", type: ActionCommentComponent, selector: "action-comment", inputs: ["count"], outputs: ["commentClick"] }, { kind: "component", type: DsMobileCardInlineFileComponent, selector: "ds-mobile-card-inline-file", inputs: ["fileName", "fileSize", "variant", "layout", "fileUrl"], outputs: ["fileClick"] }, { kind: "component", type: DsIconComponent, selector: "ds-icon", inputs: ["name", "size", "color", "interactive"] }, { kind: "component", type: DsMobileInlinePhotoComponent, selector: "ds-mobile-inline-photo", inputs: ["images", "author", "maxVisible"], outputs: ["photoClick"] }, { kind: "component", type: IonInfiniteScroll, selector: "ion-infinite-scroll", inputs: ["disabled", "position", "threshold"] }, { kind: "component", type: IonInfiniteScrollContent, selector: "ion-infinite-scroll-content", inputs: ["loadingSpinner", "loadingText"] }] });
15920
15946
  }
15921
15947
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: MobileCommunityPageComponent, decorators: [{
15922
15948
  type: Component,
@@ -16156,58 +16182,72 @@ class MobileHandbookPageComponent {
16156
16182
  title: 'El',
16157
16183
  description: 'Hovedeltavle placeret i kælderrum B-12. Nødafbryderknap er ved hovedindgangen. Alle kredsløb er mærket.',
16158
16184
  contacts: [
16159
- { name: 'ElektroTek ApS', initials: 'E', contactPerson: 'Lars Nielsen', phoneNumber: '+45 23 45 67 89' }
16160
- ]
16185
+ {
16186
+ name: 'ElektroTek ApS',
16187
+ initials: 'E',
16188
+ contactPerson: 'Lars Nielsen',
16189
+ phoneNumber: '+45 23 45 67 89',
16190
+ },
16191
+ ],
16161
16192
  },
16162
16193
  {
16163
16194
  title: 'Elektrisk diagram',
16164
16195
  description: 'Komplet diagram over bygningens elektriske installation med alle kredsløb og afbrydere.',
16165
- attachments: [
16166
- { name: 'Elektrisk_Diagram.pdf', type: 'pdf' }
16167
- ]
16196
+ attachments: [{ name: 'Elektrisk_Diagram.pdf', type: 'pdf' }],
16168
16197
  },
16169
16198
  {
16170
16199
  title: 'Vandforsyning',
16171
16200
  description: 'Hovedvandhane er placeret i kælderens tekniske rum. Individuelle lejlighedsafspærringer er i gangpanelerne. Vandtryk overvåges automatisk.',
16172
16201
  contacts: [
16173
- { name: 'VVS Hansen', initials: 'V', contactPerson: 'Peter Hansen', phoneNumber: '+45 34 56 78 90' }
16174
- ]
16202
+ {
16203
+ name: 'VVS Hansen',
16204
+ initials: 'V',
16205
+ contactPerson: 'Peter Hansen',
16206
+ phoneNumber: '+45 34 56 78 90',
16207
+ },
16208
+ ],
16175
16209
  },
16176
16210
  {
16177
16211
  title: 'Varmesystem',
16178
16212
  description: 'Fjernvarmetilslutning i kælder. Termostater i hver enhed kan justeres individuelt. Systemet vedligeholdes kvartalsvis af certificerede teknikere.',
16179
16213
  contacts: [
16180
- { name: 'Varme Service A/S', initials: 'V', contactPerson: 'Maria Jensen', phoneNumber: '+45 45 67 89 01' }
16181
- ]
16214
+ {
16215
+ name: 'Varme Service A/S',
16216
+ initials: 'V',
16217
+ contactPerson: 'Maria Jensen',
16218
+ phoneNumber: '+45 45 67 89 01',
16219
+ },
16220
+ ],
16182
16221
  },
16183
16222
  {
16184
16223
  title: 'Varmeanlæg dokumentation',
16185
16224
  description: 'Teknisk dokumentation og vedligeholdelseshistorik for bygningens varmesystem.',
16186
16225
  attachments: [
16187
16226
  { name: 'Varmeplan.pdf', type: 'pdf' },
16188
- { name: 'Vedligeholdelseslog.pdf', type: 'pdf' }
16189
- ]
16227
+ { name: 'Vedligeholdelseslog.pdf', type: 'pdf' },
16228
+ ],
16190
16229
  },
16191
16230
  {
16192
16231
  title: 'Internet & TV',
16193
16232
  description: 'Fiberforbindelse i bygningen. Distributionspanel er i stueetageteknisk rum. Hver lejlighed har ethernet-stik i stue og soveværelser.',
16194
16233
  contacts: [
16195
- { name: 'TeleCom Solutions', initials: 'T', contactPerson: 'Anders Petersen', phoneNumber: '+45 56 78 90 12' }
16196
- ]
16234
+ {
16235
+ name: 'TeleCom Solutions',
16236
+ initials: 'T',
16237
+ contactPerson: 'Anders Petersen',
16238
+ phoneNumber: '+45 56 78 90 12',
16239
+ },
16240
+ ],
16197
16241
  },
16198
16242
  {
16199
16243
  title: 'Netværksopsætning guide',
16200
- attachments: [
16201
- { name: 'Netværksopsætning.pdf', type: 'pdf' }
16202
- ]
16244
+ attachments: [{ name: 'Netværksopsætning.pdf', type: 'pdf' }],
16203
16245
  },
16204
16246
  {
16205
16247
  title: 'Affaldshåndtering',
16206
16248
  description: 'Affaldssorteringsstation placeret i gården. Afhentninger: Dagrenovation (man/tor), Genbrug (ons), Organisk (tir/fre). Storskrald kræver booking.',
16207
- attachments: [
16208
- { name: 'Affaldsretningslinjer.pdf', type: 'pdf' }
16209
- ]
16210
- }
16249
+ attachments: [{ name: 'Affaldsretningslinjer.pdf', type: 'pdf' }],
16250
+ },
16211
16251
  ];
16212
16252
  // Safety Equipment folder data
16213
16253
  sikkerhedsudstyrItems = [
@@ -16216,30 +16256,45 @@ class MobileHandbookPageComponent {
16216
16256
  description: 'Trappeopgange med nødbelysning og brandsikre døre. Postkasser placeret i indgangspartiet. Hold altid flugtveje fri.',
16217
16257
  images: [
16218
16258
  '/Assets/Dummy-photos/staircase.jpg',
16219
- '/Assets/Dummy-photos/mailboxes.jpg'
16220
- ]
16259
+ '/Assets/Dummy-photos/mailboxes.jpg',
16260
+ ],
16221
16261
  },
16222
16262
  {
16223
16263
  title: 'Hjertestarter (AED)',
16224
16264
  description: 'Automatisk hjertestarter placeret i stueetagen ved hovedindgangen. Tilgængelig 24/7. Ingen særlig uddannelse kræves - enheden guider dig gennem processen.',
16225
16265
  contacts: [
16226
- { name: 'MediTech Service', initials: 'M', contactPerson: 'John Mortensen', phoneNumber: '+45 12 34 56 78' }
16227
- ]
16266
+ {
16267
+ name: 'MediTech Service',
16268
+ initials: 'M',
16269
+ contactPerson: 'John Mortensen',
16270
+ phoneNumber: '+45 12 34 56 78',
16271
+ },
16272
+ ],
16273
+ attachments: [
16274
+ {
16275
+ name: 'Brandplan.pdf',
16276
+ type: 'pdf',
16277
+ url: 'https://portal-api.propbinder.com/Handbook/GetFile/50145267-d9a2-448b-a0e1-1af39d344818',
16278
+ },
16279
+ ],
16228
16280
  },
16229
16281
  {
16230
16282
  title: 'Brandslukningsudstyr',
16231
16283
  description: 'Brandslukkere placeret på hver etage. Eftersyn udføres årligt. Brandalarm aktiveres automatisk ved røg.',
16232
- attachments: [
16233
- { name: 'Brandplan.pdf', type: 'pdf' }
16234
- ]
16284
+ attachments: [{ name: 'Brandplan.pdf', type: 'pdf' }],
16235
16285
  },
16236
16286
  {
16237
16287
  title: 'Alarmsystem',
16238
16288
  description: 'Adgangskontrol med kodesystem ved alle indgange. Kode ændres kvartalsvis. Ved indbrud kontakt straks politiet og ejendomsadministrationen.',
16239
16289
  contacts: [
16240
- { name: 'SecureHome A/S', initials: 'S', contactPerson: 'Henrik Johansen', phoneNumber: '+45 98 76 54 32' }
16241
- ]
16242
- }
16290
+ {
16291
+ name: 'SecureHome A/S',
16292
+ initials: 'S',
16293
+ contactPerson: 'Henrik Johansen',
16294
+ phoneNumber: '+45 98 76 54 32',
16295
+ },
16296
+ ],
16297
+ },
16243
16298
  ];
16244
16299
  // Service Contracts folder data
16245
16300
  serviceContractsItems = [
@@ -16247,100 +16302,124 @@ class MobileHandbookPageComponent {
16247
16302
  title: 'Rengøringsservice',
16248
16303
  description: 'Ugentlig rengøring af fællesarealer inklusiv indgangshal, trapper og elevatorer. Hovedrengøring kvartalsvis. Service leveres mandag-fredag, 6:00-9:00.',
16249
16304
  contacts: [
16250
- { name: 'CleanCo Denmark', initials: 'C', contactPerson: 'Anne Kristensen', phoneNumber: '+45 89 01 23 45' }
16251
- ]
16305
+ {
16306
+ name: 'CleanCo Denmark',
16307
+ initials: 'C',
16308
+ contactPerson: 'Anne Kristensen',
16309
+ phoneNumber: '+45 89 01 23 45',
16310
+ },
16311
+ ],
16252
16312
  },
16253
16313
  {
16254
16314
  title: 'Rengøringskontrakt',
16255
16315
  attachments: [
16256
16316
  { name: 'Rengøringskontrakt_2024.pdf', type: 'pdf' },
16257
- { name: 'Rengøringsplan.pdf', type: 'pdf' }
16258
- ]
16317
+ { name: 'Rengøringsplan.pdf', type: 'pdf' },
16318
+ ],
16259
16319
  },
16260
16320
  {
16261
16321
  title: 'Udendørs arealer',
16262
16322
  description: 'Fælles grønne områder med bede, siddepladser og terrasse. Beboere må frit benytte området. Respektér planterne og hold området pænt.',
16263
16323
  images: [
16264
16324
  '/Assets/Dummy-photos/park.jpg',
16265
- '/Assets/Dummy-photos/yard.jpg'
16266
- ]
16325
+ '/Assets/Dummy-photos/yard.jpg',
16326
+ ],
16267
16327
  },
16268
16328
  {
16269
16329
  title: 'Havevedligeholdelse',
16270
16330
  description: 'Professionel havepleje inklusiv plæneklipning, hækklipning og blomsterbedvedligeholdelse. Vintersnefjerning inkluderet.',
16271
16331
  contacts: [
16272
- { name: 'Green Gardens ApS', initials: 'G', contactPerson: 'Michael Olsen', phoneNumber: '+45 90 12 34 56' }
16273
- ]
16332
+ {
16333
+ name: 'Green Gardens ApS',
16334
+ initials: 'G',
16335
+ contactPerson: 'Michael Olsen',
16336
+ phoneNumber: '+45 90 12 34 56',
16337
+ },
16338
+ ],
16274
16339
  },
16275
16340
  {
16276
16341
  title: 'Haveserviceaftale',
16277
- attachments: [
16278
- { name: 'Haveserviceaftale.pdf', type: 'pdf' }
16279
- ]
16342
+ attachments: [{ name: 'Haveserviceaftale.pdf', type: 'pdf' }],
16280
16343
  },
16281
16344
  {
16282
16345
  title: 'Vinduespolering',
16283
16346
  description: 'Professionel vinduespoleringsservice for alle udvendige vinduer to gange årligt - forår og efterår.',
16284
16347
  contacts: [
16285
- { name: 'Crystal Clear Windows', initials: 'C', contactPerson: 'Lene Schmidt', phoneNumber: '+45 01 23 45 67' }
16286
- ]
16348
+ {
16349
+ name: 'Crystal Clear Windows',
16350
+ initials: 'C',
16351
+ contactPerson: 'Lene Schmidt',
16352
+ phoneNumber: '+45 01 23 45 67',
16353
+ },
16354
+ ],
16287
16355
  },
16288
16356
  {
16289
16357
  title: 'Sikkerhedsservice',
16290
16358
  description: '24/7 overvågningsservice med alarmrespons. Direkte forbindelse til politi og brandvæsen.',
16291
16359
  contacts: [
16292
- { name: 'SecureHome A/S', initials: 'S', contactPerson: 'Henrik Johansen', phoneNumber: '+45 12 34 56 78' }
16293
- ]
16360
+ {
16361
+ name: 'SecureHome A/S',
16362
+ initials: 'S',
16363
+ contactPerson: 'Henrik Johansen',
16364
+ phoneNumber: '+45 12 34 56 78',
16365
+ },
16366
+ ],
16294
16367
  },
16295
16368
  {
16296
16369
  title: 'Sikkerhedskontrakt og procedurer',
16297
16370
  attachments: [
16298
16371
  { name: 'Sikkerhedskontrakt.pdf', type: 'pdf' },
16299
- { name: 'Nødprocedurer.pdf', type: 'pdf' }
16300
- ]
16301
- }
16372
+ { name: 'Nødprocedurer.pdf', type: 'pdf' },
16373
+ ],
16374
+ },
16302
16375
  ];
16303
16376
  // Equipment folder data
16304
16377
  equipmentItems = [
16305
16378
  {
16306
16379
  title: 'Balkon udsigt',
16307
16380
  description: 'Eksempel på udsigt fra øverste etagers balkoner. Flere lejligheder har privat altan med fantastisk udsyn.',
16308
- images: [
16309
- '/Assets/Dummy-photos/balcony-view.jpg'
16310
- ]
16381
+ images: ['/Assets/Dummy-photos/balcony-view.jpg'],
16311
16382
  },
16312
16383
  {
16313
16384
  title: 'Vaskerum',
16314
16385
  description: 'Fælles vaskerum med 4 vaskemaskiner og 4 tørretumblere. Bookingsystem tilgængeligt via beboerportal. Maskiner accepterer betalingskort. Åbningstider: 7:00-22:00.',
16315
16386
  contacts: [
16316
- { name: 'WashTech Service', initials: 'W', contactPerson: 'Kirsten Berg', phoneNumber: '+45 34 56 78 90' }
16317
- ]
16387
+ {
16388
+ name: 'WashTech Service',
16389
+ initials: 'W',
16390
+ contactPerson: 'Kirsten Berg',
16391
+ phoneNumber: '+45 34 56 78 90',
16392
+ },
16393
+ ],
16318
16394
  },
16319
16395
  {
16320
16396
  title: 'Vaskeri instruktioner',
16321
16397
  attachments: [
16322
16398
  { name: 'Vaskeinstruktioner.pdf', type: 'pdf' },
16323
- { name: 'Bookingguide.pdf', type: 'pdf' }
16324
- ]
16399
+ { name: 'Bookingguide.pdf', type: 'pdf' },
16400
+ ],
16325
16401
  },
16326
16402
  {
16327
16403
  title: 'Vedligeholdelse og reparationer',
16328
16404
  description: 'Ved behov for reparationer eller vedligeholdelse i din lejlighed, kontakt vores hausmeister. Akutte problemer håndteres samme dag.',
16329
- images: [
16330
- '/Assets/Dummy-photos/handyman.jpg'
16331
- ],
16405
+ images: ['/Assets/Dummy-photos/handyman.jpg'],
16332
16406
  contacts: [
16333
- { name: 'Hausmeister Service', initials: 'H', contactPerson: 'Erik Sørensen', phoneNumber: '+45 56 78 90 12' }
16334
- ]
16407
+ {
16408
+ name: 'Hausmeister Service',
16409
+ initials: 'H',
16410
+ contactPerson: 'Erik Sørensen',
16411
+ phoneNumber: '+45 56 78 90 12',
16412
+ },
16413
+ ],
16335
16414
  },
16336
16415
  {
16337
16416
  title: 'Værktøjsudlån',
16338
16417
  description: 'Basis håndværktøj tilgængeligt til beboerbrug. Kvittér for værktøj ved receptionen. Returnér inden for 48 timer.',
16339
16418
  attachments: [
16340
16419
  { name: 'Værktøjsliste.pdf', type: 'pdf' },
16341
- { name: 'Udlånspolitik.pdf', type: 'pdf' }
16342
- ]
16343
- }
16420
+ { name: 'Udlånspolitik.pdf', type: 'pdf' },
16421
+ ],
16422
+ },
16344
16423
  ];
16345
16424
  constructor(userService) {
16346
16425
  this.userService = userService;
@@ -16358,8 +16437,8 @@ class MobileHandbookPageComponent {
16358
16437
  title="Håndbog"
16359
16438
  [avatarInitials]="userService.avatarInitials()"
16360
16439
  [avatarType]="userService.avatarType()"
16361
- (refresh)="handleRefresh($event)">
16362
-
16440
+ (refresh)="handleRefresh($event)"
16441
+ >
16363
16442
  <ds-mobile-content>
16364
16443
  <ds-mobile-content-section>
16365
16444
  <div class="folders-grid">
@@ -16368,7 +16447,8 @@ class MobileHandbookPageComponent {
16368
16447
  [iconName]="'remixLightbulbLine'"
16369
16448
  [itemCount]="8"
16370
16449
  [label]="'Forsyninger'"
16371
- [items]="utilitiesItems">
16450
+ [items]="utilitiesItems"
16451
+ >
16372
16452
  </ds-mobile-handbook-folder>
16373
16453
 
16374
16454
  <ds-mobile-handbook-folder
@@ -16376,7 +16456,8 @@ class MobileHandbookPageComponent {
16376
16456
  [iconName]="'remixKey2Line'"
16377
16457
  [itemCount]="4"
16378
16458
  [label]="'Sikkerhedsudstyr'"
16379
- [items]="sikkerhedsudstyrItems">
16459
+ [items]="sikkerhedsudstyrItems"
16460
+ >
16380
16461
  </ds-mobile-handbook-folder>
16381
16462
 
16382
16463
  <ds-mobile-handbook-folder
@@ -16384,7 +16465,8 @@ class MobileHandbookPageComponent {
16384
16465
  [iconName]="'remixFileList3Line'"
16385
16466
  [itemCount]="8"
16386
16467
  [label]="'Servicekontrakter'"
16387
- [items]="serviceContractsItems">
16468
+ [items]="serviceContractsItems"
16469
+ >
16388
16470
  </ds-mobile-handbook-folder>
16389
16471
 
16390
16472
  <ds-mobile-handbook-folder
@@ -16392,7 +16474,8 @@ class MobileHandbookPageComponent {
16392
16474
  [iconName]="'remixToolsLine'"
16393
16475
  [itemCount]="5"
16394
16476
  [label]="'Udstyr'"
16395
- [items]="equipmentItems">
16477
+ [items]="equipmentItems"
16478
+ >
16396
16479
  </ds-mobile-handbook-folder>
16397
16480
  </div>
16398
16481
  </ds-mobile-content-section>
@@ -16406,14 +16489,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
16406
16489
  DsMobilePageMainComponent,
16407
16490
  DsMobileContentComponent,
16408
16491
  DsMobileContentSectionComponent,
16409
- DsMobileHandbookFolderComponent
16492
+ DsMobileHandbookFolderComponent,
16410
16493
  ], template: `
16411
16494
  <ds-mobile-page-main
16412
16495
  title="Håndbog"
16413
16496
  [avatarInitials]="userService.avatarInitials()"
16414
16497
  [avatarType]="userService.avatarType()"
16415
- (refresh)="handleRefresh($event)">
16416
-
16498
+ (refresh)="handleRefresh($event)"
16499
+ >
16417
16500
  <ds-mobile-content>
16418
16501
  <ds-mobile-content-section>
16419
16502
  <div class="folders-grid">
@@ -16422,7 +16505,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
16422
16505
  [iconName]="'remixLightbulbLine'"
16423
16506
  [itemCount]="8"
16424
16507
  [label]="'Forsyninger'"
16425
- [items]="utilitiesItems">
16508
+ [items]="utilitiesItems"
16509
+ >
16426
16510
  </ds-mobile-handbook-folder>
16427
16511
 
16428
16512
  <ds-mobile-handbook-folder
@@ -16430,7 +16514,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
16430
16514
  [iconName]="'remixKey2Line'"
16431
16515
  [itemCount]="4"
16432
16516
  [label]="'Sikkerhedsudstyr'"
16433
- [items]="sikkerhedsudstyrItems">
16517
+ [items]="sikkerhedsudstyrItems"
16518
+ >
16434
16519
  </ds-mobile-handbook-folder>
16435
16520
 
16436
16521
  <ds-mobile-handbook-folder
@@ -16438,7 +16523,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
16438
16523
  [iconName]="'remixFileList3Line'"
16439
16524
  [itemCount]="8"
16440
16525
  [label]="'Servicekontrakter'"
16441
- [items]="serviceContractsItems">
16526
+ [items]="serviceContractsItems"
16527
+ >
16442
16528
  </ds-mobile-handbook-folder>
16443
16529
 
16444
16530
  <ds-mobile-handbook-folder
@@ -16446,7 +16532,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
16446
16532
  [iconName]="'remixToolsLine'"
16447
16533
  [itemCount]="5"
16448
16534
  [label]="'Udstyr'"
16449
- [items]="equipmentItems">
16535
+ [items]="equipmentItems"
16536
+ >
16450
16537
  </ds-mobile-handbook-folder>
16451
16538
  </div>
16452
16539
  </ds-mobile-content-section>
@@ -16623,7 +16710,7 @@ class MobileHomePageComponent {
16623
16710
  </div>
16624
16711
  </ds-mobile-content>
16625
16712
  </ds-mobile-page-main>
16626
- `, isInline: true, styles: [".section-headline{font-size:var(--font-size-sm);font-weight:600;color:var(--text-color-default-primary);margin:0;letter-spacing:-.2px;display:flex;align-items:center;gap:6px;padding:0}.pinned-posts-section{margin:-12px -12px 0;padding:0 12px 12px;box-shadow:var(--box-shadow-sm);border-radius:16px;border:1px solid var(--border-color-default)}.pinned-posts-section .section-headline{padding:16px 0}.content-section{display:flex;flex-direction:column;gap:12px}.items-container{display:flex;flex-direction:column;gap:4px}\n"], dependencies: [{ kind: "component", type: DsIconComponent, selector: "ds-icon", inputs: ["name", "size", "color", "interactive"] }, { kind: "component", type: DsMobilePageMainComponent, selector: "ds-mobile-page-main", inputs: ["title", "headerTitle", "headerSubtitle", "avatarType", "avatarInitials", "avatarSrc", "avatarIconName", "showRefresh", "showCondensedHeader", "scrollThreshold", "headerFadeDistance", "profileMenuItems"], outputs: ["avatarClick", "profileActionSelected", "refresh", "scroll"] }, { kind: "component", type: DsMobileHeaderContentComponent, selector: "ds-mobile-header-content" }, { kind: "component", type: DsMobileHeaderContentTileComponent, selector: "ds-mobile-header-content-tile" }, { kind: "component", type: TileIconComponent, selector: "tile-icon" }, { kind: "component", type: TileContentComponent, selector: "tile-content" }, { kind: "component", type: TileLabelComponent, selector: "tile-label" }, { kind: "component", type: TileValueComponent, selector: "tile-value" }, { kind: "component", type: DsMobileContentComponent, selector: "ds-mobile-content", inputs: ["layout"] }, { kind: "component", type: DsMobileCardInlineContactComponent, selector: "ds-mobile-card-inline-contact", inputs: ["name", "initials", "contactPerson", "phoneNumber", "layout", "clickable", "showChevron"], outputs: ["contactClick"] }, { kind: "component", type: DsMobileCardInlineFileComponent, selector: "ds-mobile-card-inline-file", inputs: ["fileName", "fileSize", "variant", "layout"], outputs: ["fileClick"] }, { kind: "component", type: DsMobileInteractiveListItemPostComponent, selector: "ds-mobile-interactive-list-item-post", inputs: ["authorName", "authorRole", "timestamp", "avatarInitials", "avatarType", "avatarSrc", "avatarIconName", "showBadge", "variant", "clickable"], outputs: ["postClick", "commentClick", "longPress"] }, { kind: "component", type: PostContentComponent, selector: "post-content" }, { kind: "component", type: PostTextComponent, selector: "post-text" }, { kind: "component", type: PostAttachmentsComponent, selector: "post-attachments" }, { kind: "component", type: PostActionsComponent, selector: "post-actions" }, { kind: "component", type: ActionLikeComponent, selector: "action-like", inputs: ["active", "count"], outputs: ["activeChange", "countChange", "likeClick"] }, { kind: "component", type: ActionCommentComponent, selector: "action-comment", inputs: ["count"], outputs: ["commentClick"] }] });
16713
+ `, isInline: true, styles: [".section-headline{font-size:var(--font-size-sm);font-weight:600;color:var(--text-color-default-primary);margin:0;letter-spacing:-.2px;display:flex;align-items:center;gap:6px;padding:0}.pinned-posts-section{margin:-12px -12px 0;padding:0 12px 12px;box-shadow:var(--box-shadow-sm);border-radius:16px;border:1px solid var(--border-color-default)}.pinned-posts-section .section-headline{padding:16px 0}.content-section{display:flex;flex-direction:column;gap:12px}.items-container{display:flex;flex-direction:column;gap:4px}\n"], dependencies: [{ kind: "component", type: DsIconComponent, selector: "ds-icon", inputs: ["name", "size", "color", "interactive"] }, { kind: "component", type: DsMobilePageMainComponent, selector: "ds-mobile-page-main", inputs: ["title", "headerTitle", "headerSubtitle", "avatarType", "avatarInitials", "avatarSrc", "avatarIconName", "showRefresh", "showCondensedHeader", "scrollThreshold", "headerFadeDistance", "profileMenuItems"], outputs: ["avatarClick", "profileActionSelected", "refresh", "scroll"] }, { kind: "component", type: DsMobileHeaderContentComponent, selector: "ds-mobile-header-content" }, { kind: "component", type: DsMobileHeaderContentTileComponent, selector: "ds-mobile-header-content-tile" }, { kind: "component", type: TileIconComponent, selector: "tile-icon" }, { kind: "component", type: TileContentComponent, selector: "tile-content" }, { kind: "component", type: TileLabelComponent, selector: "tile-label" }, { kind: "component", type: TileValueComponent, selector: "tile-value" }, { kind: "component", type: DsMobileContentComponent, selector: "ds-mobile-content", inputs: ["layout"] }, { kind: "component", type: DsMobileCardInlineContactComponent, selector: "ds-mobile-card-inline-contact", inputs: ["name", "initials", "contactPerson", "phoneNumber", "layout", "clickable", "showChevron"], outputs: ["contactClick"] }, { kind: "component", type: DsMobileCardInlineFileComponent, selector: "ds-mobile-card-inline-file", inputs: ["fileName", "fileSize", "variant", "layout", "fileUrl"], outputs: ["fileClick"] }, { kind: "component", type: DsMobileInteractiveListItemPostComponent, selector: "ds-mobile-interactive-list-item-post", inputs: ["authorName", "authorRole", "timestamp", "avatarInitials", "avatarType", "avatarSrc", "avatarIconName", "showBadge", "variant", "clickable"], outputs: ["postClick", "commentClick", "longPress"] }, { kind: "component", type: PostContentComponent, selector: "post-content" }, { kind: "component", type: PostTextComponent, selector: "post-text" }, { kind: "component", type: PostAttachmentsComponent, selector: "post-attachments" }, { kind: "component", type: PostActionsComponent, selector: "post-actions" }, { kind: "component", type: ActionLikeComponent, selector: "action-like", inputs: ["active", "count"], outputs: ["activeChange", "countChange", "likeClick"] }, { kind: "component", type: ActionCommentComponent, selector: "action-comment", inputs: ["count"], outputs: ["commentClick"] }] });
16627
16714
  }
16628
16715
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: MobileHomePageComponent, decorators: [{
16629
16716
  type: Component,