@ship-ui/core 0.14.22 → 0.15.0

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.
package/README.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  A modern signal based and zoneless compatable UI library for Angular visit our website [shipui.com](https://shipui.com) for more info.
4
4
 
5
+ Docs can be found at [docs.shipui.com](https://docs.shipui.com)
6
+
5
7
  ## Base setup
6
8
 
7
9
  To start using ShipUI make sure you're using angular 19 or newer.
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { inject, ElementRef, Renderer2, ChangeDetectionStrategy, Component, signal, DestroyRef, InjectionToken, input, computed, viewChild, effect, HostListener, NgModule, Injectable, model, output, ApplicationRef, createComponent, isSignal, OutputEmitterRef, contentChild, contentChildren, afterNextRender, assertInInjectionContext, Injector, HostBinding, TemplateRef, runInInjectionContext, Directive, ChangeDetectorRef, viewChildren, ViewContainerRef, EnvironmentInjector } from '@angular/core';
2
+ import { inject, ElementRef, Renderer2, ChangeDetectionStrategy, Component, signal, DestroyRef, InjectionToken, input, computed, viewChild, effect, HostListener, NgModule, Injectable, DOCUMENT, model, output, ApplicationRef, createComponent, isSignal, OutputEmitterRef, contentChild, contentChildren, afterNextRender, assertInInjectionContext, Injector, HostBinding, TemplateRef, runInInjectionContext, Directive, ChangeDetectorRef, viewChildren, ViewContainerRef, EnvironmentInjector } from '@angular/core';
3
3
  import { DatePipe, NgTemplateOutlet } from '@angular/common';
4
4
  import { NgModel } from '@angular/forms';
5
5
  import { SIGNAL } from '@angular/core/primitives/signals';
@@ -51,7 +51,7 @@ function classMutationSignal() {
51
51
  }
52
52
  }
53
53
  });
54
- observer.observe(element, { attributes: true });
54
+ observer.observe(element, { attributes: true, attributeFilter: ['class'] });
55
55
  destroyRef.onDestroy(() => observer.disconnect());
56
56
  return classListSignal.asReadonly();
57
57
  }
@@ -355,6 +355,7 @@ const DEFAULT_OPTIONS$1 = {
355
355
  };
356
356
  class ShipDialogComponent {
357
357
  constructor() {
358
+ this.#document = inject(DOCUMENT);
358
359
  this.#shConfig = inject(SHIP_CONFIG, { optional: true });
359
360
  this.dialogRef = viewChild('dialogRef', ...(ngDevMode ? [{ debugName: "dialogRef" }] : []));
360
361
  this.isOpen = model(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : []));
@@ -380,7 +381,7 @@ class ShipDialogComponent {
380
381
  }, {
381
382
  signal: this.abortController?.signal,
382
383
  });
383
- document.addEventListener('keydown', (e) => {
384
+ this.#document.addEventListener('keydown', (e) => {
384
385
  if (e.key === 'Escape' && !this.defaultOptionMerge().closeOnEsc) {
385
386
  e.preventDefault();
386
387
  }
@@ -397,6 +398,7 @@ class ShipDialogComponent {
397
398
  }
398
399
  }, ...(ngDevMode ? [{ debugName: "isOpenEffect" }] : []));
399
400
  }
401
+ #document;
400
402
  #shConfig;
401
403
  ngOnDestroy() {
402
404
  this.abortController?.abort();
@@ -452,13 +454,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImpor
452
454
 
453
455
  class ShipDialogService {
454
456
  constructor() {
455
- this.#bodyEl = typeof document !== 'undefined' ? document.querySelector('body') : null;
457
+ this.#document = inject(DOCUMENT);
458
+ this.#bodyEl = this.#document.querySelector('body');
456
459
  this.#appRef = inject(ApplicationRef);
457
460
  this.compRef = null;
458
461
  this.insertedCompRef = null;
459
462
  this.closedFieldSub = null;
460
463
  this.compClosedSub = null;
461
464
  }
465
+ #document;
462
466
  #bodyEl;
463
467
  #appRef;
464
468
  open(component, options) {
@@ -515,12 +519,12 @@ class ShipDialogService {
515
519
  };
516
520
  }
517
521
  #createEl() {
518
- const wrapperEl = document.createElement('sh-dialog-ref');
522
+ const wrapperEl = this.#document.createElement('sh-dialog-ref');
519
523
  wrapperEl.id = 'sh-dialog-ref';
520
- if (!document.getElementById('sh-dialog-ref')) {
524
+ if (!this.#document.getElementById('sh-dialog-ref')) {
521
525
  this.#bodyEl?.append(wrapperEl);
522
526
  }
523
- return document.getElementById('sh-dialog-ref');
527
+ return this.#document.getElementById('sh-dialog-ref');
524
528
  }
525
529
  #cleanupRefs() {
526
530
  if (this.insertedCompRef) {
@@ -550,7 +554,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImpor
550
554
  class ShipButtonGroupComponent {
551
555
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: ShipButtonGroupComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
552
556
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.6", type: ShipButtonGroupComponent, isStandalone: true, selector: "sh-button-group", ngImport: i0, template: `
553
- <ng-content></ng-content>
557
+ <ng-content />
554
558
  `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
555
559
  }
556
560
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: ShipButtonGroupComponent, decorators: [{
@@ -559,7 +563,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImpor
559
563
  selector: 'sh-button-group',
560
564
  imports: [],
561
565
  template: `
562
- <ng-content></ng-content>
566
+ <ng-content />
563
567
  `,
564
568
  changeDetection: ChangeDetectionStrategy.OnPush,
565
569
  }]
@@ -590,7 +594,7 @@ class ShipCardComponent {
590
594
  #shConfig;
591
595
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: ShipCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
592
596
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.6", type: ShipCardComponent, isStandalone: true, selector: "sh-card", host: { properties: { "class": "class()" } }, ngImport: i0, template: `
593
- <ng-content></ng-content>
597
+ <ng-content />
594
598
  `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
595
599
  }
596
600
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: ShipCardComponent, decorators: [{
@@ -599,7 +603,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImpor
599
603
  selector: 'sh-card',
600
604
  imports: [],
601
605
  template: `
602
- <ng-content></ng-content>
606
+ <ng-content />
603
607
  `,
604
608
  changeDetection: ChangeDetectionStrategy.OnPush,
605
609
  host: {
@@ -611,14 +615,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImpor
611
615
  class ShipCheckboxComponent {
612
616
  constructor() {
613
617
  this.currentClassList = classMutationSignal();
614
- this.showClasses = computed(() => {
615
- const classArr = this.currentClassList().split(' ');
616
- return classArr;
617
- }, ...(ngDevMode ? [{ debugName: "showClasses" }] : []));
618
618
  }
619
619
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: ShipCheckboxComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
620
620
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.6", type: ShipCheckboxComponent, isStandalone: true, selector: "sh-checkbox", ngImport: i0, template: `
621
- <div class="box sh-sheet" [class]="showClasses()">
621
+ <div class="box sh-sheet" [class]="currentClassList()">
622
622
  <sh-icon class="inherit default-indicator">check-bold</sh-icon>
623
623
  <sh-icon class="inherit indeterminate-indicator">minus-bold</sh-icon>
624
624
  </div>
@@ -632,7 +632,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImpor
632
632
  selector: 'sh-checkbox',
633
633
  imports: [ShipIconComponent],
634
634
  template: `
635
- <div class="box sh-sheet" [class]="showClasses()">
635
+ <div class="box sh-sheet" [class]="currentClassList()">
636
636
  <sh-icon class="inherit default-indicator">check-bold</sh-icon>
637
637
  <sh-icon class="inherit indeterminate-indicator">minus-bold</sh-icon>
638
638
  </div>
@@ -645,14 +645,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImpor
645
645
 
646
646
  class ShipChipComponent {
647
647
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: ShipChipComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
648
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.6", type: ShipChipComponent, isStandalone: true, selector: "sh-chip", host: { classAttribute: "sh-sheet" }, ngImport: i0, template: '<div><ng-content></ng-content></div>', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
648
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.6", type: ShipChipComponent, isStandalone: true, selector: "sh-chip", host: { classAttribute: "sh-sheet" }, ngImport: i0, template: '<div><ng-content /></div>', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
649
649
  }
650
650
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: ShipChipComponent, decorators: [{
651
651
  type: Component,
652
652
  args: [{
653
653
  selector: 'sh-chip',
654
654
  imports: [],
655
- template: '<div><ng-content></ng-content></div>',
655
+ template: '<div><ng-content /></div>',
656
656
  changeDetection: ChangeDetectionStrategy.OnPush,
657
657
  host: {
658
658
  class: 'sh-sheet',
@@ -665,6 +665,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImpor
665
665
  // - Add alpha support
666
666
  class ShipColorPickerComponent {
667
667
  constructor() {
668
+ this.#document = inject(DOCUMENT);
668
669
  this.canvasRef = viewChild.required('colorCanvas');
669
670
  this.canvasData = signal(null, ...(ngDevMode ? [{ debugName: "canvasData" }] : []));
670
671
  this.showDarkColors = input(false, ...(ngDevMode ? [{ debugName: "showDarkColors" }] : []));
@@ -710,6 +711,7 @@ class ShipColorPickerComponent {
710
711
  }, ...(ngDevMode ? [{ debugName: "renderingTypeEffect" }] : []));
711
712
  this.initColor = null;
712
713
  }
714
+ #document;
713
715
  onResize() {
714
716
  this.setCanvasSize();
715
717
  }
@@ -775,22 +777,22 @@ class ShipColorPickerComponent {
775
777
  this.isDragging.set(true);
776
778
  this.updateColorAndMarker(event);
777
779
  });
778
- document.addEventListener('mousemove', (event) => {
780
+ this.#document.addEventListener('mousemove', (event) => {
779
781
  if (this.isDragging()) {
780
782
  event.preventDefault();
781
783
  this.updateColorAndMarker(event, true);
782
784
  }
783
785
  });
784
- document.addEventListener('mouseup', () => this.isDragging.set(false));
786
+ this.#document.addEventListener('mouseup', () => this.isDragging.set(false));
785
787
  canvas.addEventListener('touchstart', (_) => this.isDragging.set(true));
786
- document.addEventListener('touchmove', (event) => {
788
+ this.#document.addEventListener('touchmove', (event) => {
787
789
  if (this.isDragging()) {
788
790
  event.preventDefault();
789
791
  this.updateColorAndMarker(event.touches[0], true);
790
792
  }
791
793
  });
792
- document.addEventListener('touchend', () => this.isDragging.set(false));
793
- document.addEventListener('touchcancel', () => this.isDragging.set(false));
794
+ this.#document.addEventListener('touchend', () => this.isDragging.set(false));
795
+ this.#document.addEventListener('touchcancel', () => this.isDragging.set(false));
794
796
  }
795
797
  setCanvasSize() {
796
798
  const canvas = this.canvasRef()?.nativeElement;
@@ -1015,6 +1017,7 @@ const DEFAULT_OPTIONS = {
1015
1017
  };
1016
1018
  class ShipPopoverComponent {
1017
1019
  constructor() {
1020
+ this.#document = inject(DOCUMENT);
1018
1021
  this.#BASE_SPACE = 4;
1019
1022
  this.SUPPORTS_ANCHOR = typeof CSS !== 'undefined' && CSS.supports('position-anchor', '--abc') && CSS.supports('anchor-name', '--abc');
1020
1023
  this.asMultiLayer = input(false, ...(ngDevMode ? [{ debugName: "asMultiLayer" }] : []));
@@ -1043,7 +1046,7 @@ class ShipPopoverComponent {
1043
1046
  signal: this.openAbort?.signal,
1044
1047
  };
1045
1048
  popoverEl?.showPopover();
1046
- document.addEventListener('keydown', (e) => {
1049
+ this.#document.addEventListener('keydown', (e) => {
1047
1050
  if (e.key === 'Escape' && !this.defaultOptionMerge().closeOnEsc) {
1048
1051
  e.preventDefault();
1049
1052
  }
@@ -1065,6 +1068,7 @@ class ShipPopoverComponent {
1065
1068
  }
1066
1069
  }, ...(ngDevMode ? [{ debugName: "openEffect" }] : []));
1067
1070
  }
1071
+ #document;
1068
1072
  #BASE_SPACE;
1069
1073
  toggleIsOpen(event) {
1070
1074
  event.preventDefault();
@@ -1087,7 +1091,7 @@ class ShipPopoverComponent {
1087
1091
  }
1088
1092
  parent = parent.parentElement;
1089
1093
  }
1090
- return document.documentElement;
1094
+ return this.#document.documentElement;
1091
1095
  }
1092
1096
  #calculateMenuPosition() {
1093
1097
  const triggerRect = this.triggerRef()?.nativeElement.getBoundingClientRect();
@@ -1122,12 +1126,13 @@ class ShipPopoverComponent {
1122
1126
  }
1123
1127
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: ShipPopoverComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1124
1128
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "20.1.6", type: ShipPopoverComponent, isStandalone: true, selector: "sh-popover", inputs: { asMultiLayer: { classPropertyName: "asMultiLayer", publicName: "asMultiLayer", isSignal: true, isRequired: false, transformFunction: null }, disableOpenByClick: { classPropertyName: "disableOpenByClick", publicName: "disableOpenByClick", isSignal: true, isRequired: false, transformFunction: null }, isOpen: { classPropertyName: "isOpen", publicName: "isOpen", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { isOpen: "isOpenChange", closed: "closed" }, host: { properties: { "class.multi-layer": "asMultiLayer()" } }, viewQueries: [{ propertyName: "triggerRef", first: true, predicate: ["triggerRef"], descendants: true, isSignal: true }, { propertyName: "popoverRef", first: true, predicate: ["popoverRef"], descendants: true, isSignal: true }], ngImport: i0, template: `
1125
- <div class="trigger" #triggerRef [style.anchor-name]="id()" (click)="toggleIsOpen($event)">
1129
+ <div class="trigger" #triggerRef (click)="toggleIsOpen($event)">
1126
1130
  <div class="trigger-wrapper">
1127
1131
  <ng-content select="[trigger]" />
1128
1132
  <ng-content select="button" />
1129
1133
  <ng-content select="[shButton]" />
1130
1134
  </div>
1135
+ <div class="trigger-anchor" [style.anchor-name]="id()"></div>
1131
1136
  </div>
1132
1137
 
1133
1138
  <div popover #popoverRef class="popover" [style.position-anchor]="id()" [style]="menuStyle()">
@@ -1142,12 +1147,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImpor
1142
1147
  selector: 'sh-popover',
1143
1148
  imports: [],
1144
1149
  template: `
1145
- <div class="trigger" #triggerRef [style.anchor-name]="id()" (click)="toggleIsOpen($event)">
1150
+ <div class="trigger" #triggerRef (click)="toggleIsOpen($event)">
1146
1151
  <div class="trigger-wrapper">
1147
1152
  <ng-content select="[trigger]" />
1148
1153
  <ng-content select="button" />
1149
1154
  <ng-content select="[shButton]" />
1150
1155
  </div>
1156
+ <div class="trigger-anchor" [style.anchor-name]="id()"></div>
1151
1157
  </div>
1152
1158
 
1153
1159
  <div popover #popoverRef class="popover" [style.position-anchor]="id()" [style]="menuStyle()">
@@ -2800,15 +2806,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImpor
2800
2806
  }] });
2801
2807
 
2802
2808
  class ShipRadioComponent {
2803
- #selfRef = inject(ElementRef);
2804
- onClick() {
2805
- if (this.#selfRef.nativeElement.querySelector('input')) {
2806
- this.#selfRef.nativeElement.querySelector('input').focus();
2807
- }
2809
+ constructor() {
2810
+ this.currentClassList = classMutationSignal();
2808
2811
  }
2809
2812
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: ShipRadioComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2810
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.6", type: ShipRadioComponent, isStandalone: true, selector: "sh-radio", host: { listeners: { "click": "onClick()" } }, ngImport: i0, template: `
2811
- <div class="radio"></div>
2813
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.6", type: ShipRadioComponent, isStandalone: true, selector: "sh-radio", ngImport: i0, template: `
2814
+ <div class="radio sh-sheet" [class]="currentClassList()"></div>
2812
2815
 
2813
2816
  <ng-content />
2814
2817
  `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
@@ -2819,16 +2822,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImpor
2819
2822
  selector: 'sh-radio',
2820
2823
  imports: [],
2821
2824
  template: `
2822
- <div class="radio"></div>
2825
+ <div class="radio sh-sheet" [class]="currentClassList()"></div>
2823
2826
 
2824
2827
  <ng-content />
2825
2828
  `,
2826
2829
  changeDetection: ChangeDetectionStrategy.OnPush,
2827
2830
  }]
2828
- }], propDecorators: { onClick: [{
2829
- type: HostListener,
2830
- args: ['click']
2831
- }] } });
2831
+ }] });
2832
2832
 
2833
2833
  class ShipRangeSliderComponent {
2834
2834
  constructor() {
@@ -2972,7 +2972,7 @@ class ShipRangeSliderComponent {
2972
2972
  this.#updateStateFromInput(false);
2973
2973
  }
2974
2974
  });
2975
- this.#observer.observe(this.#inputElement, { attributes: true });
2975
+ this.#observer.observe(this.#inputElement, { attributes: true, attributeFilter: MUTATION_ATTRIBUTES });
2976
2976
  }
2977
2977
  #countDecimals(value) {
2978
2978
  if (isNaN(value) || Math.floor(value) === value)
@@ -4010,6 +4010,7 @@ function watchHostClass(className) {
4010
4010
  }
4011
4011
  class ShipSidenavComponent {
4012
4012
  constructor() {
4013
+ this.#document = inject(DOCUMENT);
4013
4014
  this.#selfRef = inject(ElementRef);
4014
4015
  this.openWidth = 280;
4015
4016
  this.openWidthTreshold = this.openWidth * 0.5;
@@ -4054,16 +4055,17 @@ class ShipSidenavComponent {
4054
4055
  return this.isOpen() ? `translateX(${this.openWidth}px)` : `translateX(0px)`;
4055
4056
  }, ...(ngDevMode ? [{ debugName: "draggingStyle" }] : []));
4056
4057
  this.draggingEffect = effect(() => {
4057
- if (typeof document === 'undefined' || this.disableDrag())
4058
+ if (this.disableDrag())
4058
4059
  return;
4059
4060
  if (this.isDragging()) {
4060
- document.body.classList.add('dragging');
4061
+ this.#document.body.classList.add('dragging');
4061
4062
  }
4062
4063
  else {
4063
- document.body.classList.remove('dragging');
4064
+ this.#document.body.classList.remove('dragging');
4064
4065
  }
4065
4066
  }, ...(ngDevMode ? [{ debugName: "draggingEffect" }] : []));
4066
4067
  }
4068
+ #document;
4067
4069
  #selfRef;
4068
4070
  #closestParent;
4069
4071
  #closestParentRect;
@@ -4160,7 +4162,7 @@ class ShipSidenavComponent {
4160
4162
  </div>
4161
4163
 
4162
4164
  <main>
4163
- <ng-content></ng-content>
4165
+ <ng-content />
4164
4166
  </main>
4165
4167
  </div>
4166
4168
  `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
@@ -4201,7 +4203,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImpor
4201
4203
  </div>
4202
4204
 
4203
4205
  <main>
4204
- <ng-content></ng-content>
4206
+ <ng-content />
4205
4207
  </main>
4206
4208
  </div>
4207
4209
  `,
@@ -4306,6 +4308,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImpor
4306
4308
 
4307
4309
  class ShipSortableDirective {
4308
4310
  constructor() {
4311
+ this.#document = inject(DOCUMENT);
4309
4312
  this.#selfEl = inject((ElementRef));
4310
4313
  this.#renderer = inject(Renderer2);
4311
4314
  this.#placeholderEl = signal(null, ...(ngDevMode ? [{ debugName: "#placeholderEl" }] : []));
@@ -4388,6 +4391,7 @@ class ShipSortableDirective {
4388
4391
  }
4389
4392
  });
4390
4393
  }
4394
+ #document;
4391
4395
  #selfEl;
4392
4396
  #renderer;
4393
4397
  #placeholderEl;
@@ -4399,7 +4403,7 @@ class ShipSortableDirective {
4399
4403
  dragStart(e) {
4400
4404
  if (e.target && e.dataTransfer) {
4401
4405
  const targetElement = e.target;
4402
- const currentTarget = document.elementFromPoint(e.clientX, e.clientY);
4406
+ const currentTarget = this.#document.elementFromPoint(e.clientX, e.clientY);
4403
4407
  const isSortingHandle = currentTarget?.hasAttribute('sort-handle') || currentTarget?.closest('[sort-handle]') !== null;
4404
4408
  let draggedElement;
4405
4409
  if (isSortingHandle) {
@@ -4990,7 +4994,7 @@ class ShipToggleCardComponent {
4990
4994
 
4991
4995
  <div class="collapsable">
4992
4996
  <div class="content">
4993
- <ng-content></ng-content>
4997
+ <ng-content />
4994
4998
  </div>
4995
4999
  </div>
4996
5000
  `, isInline: true, dependencies: [{ kind: "component", type: ShipIconComponent, selector: "sh-icon" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
@@ -5011,7 +5015,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImpor
5011
5015
 
5012
5016
  <div class="collapsable">
5013
5017
  <div class="content">
5014
- <ng-content></ng-content>
5018
+ <ng-content />
5015
5019
  </div>
5016
5020
  </div>
5017
5021
  `,
@@ -5050,6 +5054,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImpor
5050
5054
 
5051
5055
  class ShipTooltipComponent {
5052
5056
  constructor() {
5057
+ this.#document = inject(DOCUMENT);
5053
5058
  this.#BASE_SPACE = 4;
5054
5059
  this.SUPPORTS_ANCHOR = CSS.supports('position-anchor', '--abc') && CSS.supports('anchor-name', '--abc');
5055
5060
  this.disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
@@ -5091,10 +5096,11 @@ class ShipTooltipComponent {
5091
5096
  this.calculateMenuPosition();
5092
5097
  const scrollableParent = this.#findScrollableParent(this.tooltipRef()?.nativeElement);
5093
5098
  scrollableParent.addEventListener('scroll', () => this.calculateMenuPosition(), { signal });
5094
- document.addEventListener('resize', () => this.calculateMenuPosition(), { signal });
5099
+ this.#document.addEventListener('resize', () => this.calculateMenuPosition(), { signal });
5095
5100
  }, ...(ngDevMode ? [{ debugName: "calcPositionEffect" }] : []));
5096
5101
  this.scrollableStyles = ['scroll', 'auto'];
5097
5102
  }
5103
+ #document;
5098
5104
  #BASE_SPACE;
5099
5105
  #findScrollableParent(element) {
5100
5106
  let parent = element.parentElement;
@@ -5105,7 +5111,7 @@ class ShipTooltipComponent {
5105
5111
  }
5106
5112
  parent = parent.parentElement;
5107
5113
  }
5108
- return document.documentElement;
5114
+ return this.#document.documentElement;
5109
5115
  }
5110
5116
  eventClose($event) {
5111
5117
  $event.stopPropagation();
@@ -5349,7 +5355,7 @@ class ShipVirtualScrollComponent {
5349
5355
  <div class="viewport" #viewport (scroll)="onScroll()">
5350
5356
  <div class="total-height" [style.height]="totalHeight() + 'px'"></div>
5351
5357
  <div class="items-container" [style.transform]="'translateY(' + translateY() + 'px)'">
5352
- <ng-content></ng-content>
5358
+ <ng-content />
5353
5359
  </div>
5354
5360
  </div>
5355
5361
  `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
@@ -5363,7 +5369,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImpor
5363
5369
  <div class="viewport" #viewport (scroll)="onScroll()">
5364
5370
  <div class="total-height" [style.height]="totalHeight() + 'px'"></div>
5365
5371
  <div class="items-container" [style.transform]="'translateY(' + translateY() + 'px)'">
5366
- <ng-content></ng-content>
5372
+ <ng-content />
5367
5373
  </div>
5368
5374
  </div>
5369
5375
  `,
@@ -5500,9 +5506,9 @@ class ShipTooltipWrapper {
5500
5506
  this.#positionAbort?.abort();
5501
5507
  }
5502
5508
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: ShipTooltipWrapper, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
5503
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.1.6", type: ShipTooltipWrapper, isStandalone: true, selector: "ship-tooltip-wrapper", inputs: { positionAnchorName: { classPropertyName: "positionAnchorName", publicName: "positionAnchorName", isSignal: true, isRequired: true, transformFunction: null }, anchorEl: { classPropertyName: "anchorEl", publicName: "anchorEl", isSignal: true, isRequired: true, transformFunction: null }, isOpen: { classPropertyName: "isOpen", publicName: "isOpen", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "tooltip" }, properties: { "attr.popover": "\"auto\"", "style.position-anchor": "positionAnchorName()", "class.below": "isBelow()" } }, ngImport: i0, template: `
5509
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.1.6", type: ShipTooltipWrapper, isStandalone: true, selector: "ship-tooltip-wrapper", inputs: { positionAnchorName: { classPropertyName: "positionAnchorName", publicName: "positionAnchorName", isSignal: true, isRequired: true, transformFunction: null }, anchorEl: { classPropertyName: "anchorEl", publicName: "anchorEl", isSignal: true, isRequired: true, transformFunction: null }, isOpen: { classPropertyName: "isOpen", publicName: "isOpen", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "tooltip" }, properties: { "attr.popover": "\"manual\"", "style.position-anchor": "positionAnchorName()", "class.below": "isBelow()" } }, ngImport: i0, template: `
5504
5510
  <div class="tooltip-content">
5505
- <ng-content></ng-content>
5511
+ <ng-content />
5506
5512
  </div>
5507
5513
  `, isInline: true }); }
5508
5514
  }
@@ -5513,12 +5519,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImpor
5513
5519
  standalone: true,
5514
5520
  template: `
5515
5521
  <div class="tooltip-content">
5516
- <ng-content></ng-content>
5522
+ <ng-content />
5517
5523
  </div>
5518
5524
  `,
5519
5525
  host: {
5520
5526
  role: 'tooltip',
5521
- '[attr.popover]': '"auto"',
5527
+ '[attr.popover]': '"manual"',
5522
5528
  '[style.position-anchor]': 'positionAnchorName()',
5523
5529
  '[class.below]': 'isBelow()',
5524
5530
  },
@@ -5533,6 +5539,7 @@ class ShipTooltipDirective {
5533
5539
  this.#environmentInjector = inject(EnvironmentInjector);
5534
5540
  this.#renderer = inject(Renderer2);
5535
5541
  this.#projectedViewRef = null;
5542
+ this.DEBOUNCE_DELAY = 500;
5536
5543
  this.anchorName = `--${generateUniqueId()}`;
5537
5544
  this.isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : []));
5538
5545
  }
@@ -5542,14 +5549,31 @@ class ShipTooltipDirective {
5542
5549
  #renderer;
5543
5550
  #projectedViewRef;
5544
5551
  onMouseEnter() {
5545
- if (openRef?.component !== this) {
5552
+ if (openRef?.component.anchorName !== this.anchorName) {
5546
5553
  this.cleanupTooltip();
5547
5554
  }
5555
+ this.cancelCleanupTimer();
5548
5556
  queueMicrotask(() => this.showTooltip());
5549
5557
  }
5558
+ onMouseLeave() {
5559
+ this.startCleanupTimer();
5560
+ }
5550
5561
  ngOnDestroy() {
5562
+ this.cancelCleanupTimer();
5551
5563
  this.cleanupTooltip();
5552
5564
  }
5565
+ startCleanupTimer() {
5566
+ this.cancelCleanupTimer();
5567
+ this.debounceTimer = setTimeout(() => {
5568
+ this.cleanupTooltip();
5569
+ }, this.DEBOUNCE_DELAY);
5570
+ }
5571
+ cancelCleanupTimer() {
5572
+ if (this.debounceTimer) {
5573
+ clearTimeout(this.debounceTimer);
5574
+ this.debounceTimer = null;
5575
+ }
5576
+ }
5553
5577
  showTooltip() {
5554
5578
  if (openRef?.wrapperComponentRef || !this.shTooltip())
5555
5579
  return;
@@ -5577,12 +5601,19 @@ class ShipTooltipDirective {
5577
5601
  openRef.wrapperComponentRef.setInput('anchorEl', this.#elementRef);
5578
5602
  openRef.wrapperComponentRef?.setInput('isOpen', this.isOpen);
5579
5603
  openRef.wrapperComponentRef.changeDetectorRef.detectChanges();
5604
+ openRef.wrapperComponentRef.location.nativeElement.addEventListener('mouseenter', () => {
5605
+ this.cancelCleanupTimer();
5606
+ });
5607
+ openRef.wrapperComponentRef.location.nativeElement.addEventListener('mouseleave', () => {
5608
+ this.startCleanupTimer();
5609
+ });
5580
5610
  setTimeout(() => {
5581
5611
  this.isOpen.set(true);
5582
5612
  });
5583
5613
  }
5584
5614
  cleanupTooltip() {
5585
5615
  if (openRef?.wrapperComponentRef) {
5616
+ openRef.component.cancelCleanupTimer();
5586
5617
  openRef.wrapperComponentRef.destroy();
5587
5618
  openRef.component.isOpen.set(false);
5588
5619
  openRef = null;
@@ -5593,7 +5624,7 @@ class ShipTooltipDirective {
5593
5624
  }
5594
5625
  }
5595
5626
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: ShipTooltipDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
5596
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.1.6", type: ShipTooltipDirective, isStandalone: true, selector: "[shTooltip]", inputs: { shTooltip: { classPropertyName: "shTooltip", publicName: "shTooltip", isSignal: true, isRequired: true, transformFunction: null } }, host: { listeners: { "mouseenter": "onMouseEnter()" }, properties: { "style.anchor-name": "anchorName", "class.active": "isOpen()" }, classAttribute: "tooltip" }, ngImport: i0 }); }
5627
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.1.6", type: ShipTooltipDirective, isStandalone: true, selector: "[shTooltip]", inputs: { shTooltip: { classPropertyName: "shTooltip", publicName: "shTooltip", isSignal: true, isRequired: true, transformFunction: null } }, host: { listeners: { "mouseenter": "onMouseEnter()", "mouseleave": "onMouseLeave()" }, properties: { "style.anchor-name": "anchorName", "class.active": "isOpen()" }, classAttribute: "tooltip" }, ngImport: i0 }); }
5597
5628
  }
5598
5629
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: ShipTooltipDirective, decorators: [{
5599
5630
  type: Directive,
@@ -5609,6 +5640,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImpor
5609
5640
  }], propDecorators: { onMouseEnter: [{
5610
5641
  type: HostListener,
5611
5642
  args: ['mouseenter']
5643
+ }], onMouseLeave: [{
5644
+ type: HostListener,
5645
+ args: ['mouseleave']
5612
5646
  }] } });
5613
5647
 
5614
5648
  /*