@ship-ui/core 0.15.15 → 0.15.17

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.
@@ -1016,6 +1016,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.0", ngImpor
1016
1016
  args: ['window:resize', ['$event']]
1017
1017
  }] } });
1018
1018
 
1019
+ const BASE_SPACE = 4;
1019
1020
  const SCROLLABLE_STYLES = ['scroll', 'auto'];
1020
1021
  const DEFAULT_OPTIONS = {
1021
1022
  width: undefined,
@@ -1026,7 +1027,6 @@ const DEFAULT_OPTIONS = {
1026
1027
  class ShipPopoverComponent {
1027
1028
  constructor() {
1028
1029
  this.#document = inject(DOCUMENT);
1029
- this.#BASE_SPACE = 4;
1030
1030
  this.SUPPORTS_ANCHOR = typeof CSS !== 'undefined' && CSS.supports('position-anchor', '--abc') && CSS.supports('anchor-name', '--abc');
1031
1031
  this.asMultiLayer = input(false, ...(ngDevMode ? [{ debugName: "asMultiLayer" }] : []));
1032
1032
  this.disableOpenByClick = input(false, ...(ngDevMode ? [{ debugName: "disableOpenByClick" }] : []));
@@ -1039,6 +1039,7 @@ class ShipPopoverComponent {
1039
1039
  }), ...(ngDevMode ? [{ debugName: "defaultOptionMerge" }] : []));
1040
1040
  this.triggerRef = viewChild.required('triggerRef');
1041
1041
  this.popoverRef = viewChild('popoverRef', ...(ngDevMode ? [{ debugName: "popoverRef" }] : []));
1042
+ this.popoverContentRef = viewChild('popoverContentRef', ...(ngDevMode ? [{ debugName: "popoverContentRef" }] : []));
1042
1043
  this.id = signal('--' + generateUniqueId(), ...(ngDevMode ? [{ debugName: "id" }] : []));
1043
1044
  this.menuStyle = signal(null, ...(ngDevMode ? [{ debugName: "menuStyle" }] : []));
1044
1045
  this.openAbort = null;
@@ -1046,16 +1047,16 @@ class ShipPopoverComponent {
1046
1047
  const open = this.isOpen();
1047
1048
  queueMicrotask(() => {
1048
1049
  const popoverEl = this.popoverRef()?.nativeElement;
1049
- if (!popoverEl)
1050
+ if (!popoverEl) {
1051
+ this.openAbort?.abort();
1052
+ this.openAbort = null;
1050
1053
  return;
1054
+ }
1051
1055
  if (open) {
1052
1056
  if (this.openAbort) {
1053
1057
  this.openAbort.abort();
1054
1058
  }
1055
1059
  this.openAbort = new AbortController();
1056
- const abortOptions = {
1057
- signal: this.openAbort?.signal,
1058
- };
1059
1060
  this.#document.addEventListener('keydown', (e) => {
1060
1061
  if (e.key === 'Escape' && !this.defaultOptionMerge().closeOnEsc) {
1061
1062
  e.preventDefault();
@@ -1063,27 +1064,32 @@ class ShipPopoverComponent {
1063
1064
  if (e.key === 'Escape' && this.defaultOptionMerge().closeOnEsc) {
1064
1065
  this.isOpen.set(false);
1065
1066
  }
1066
- }, abortOptions);
1067
+ }, {
1068
+ signal: this.openAbort?.signal,
1069
+ });
1067
1070
  popoverEl.showPopover();
1068
1071
  if (!this.SUPPORTS_ANCHOR) {
1069
1072
  setTimeout(() => {
1070
1073
  const scrollableParent = this.#findScrollableParent(popoverEl);
1071
- scrollableParent.addEventListener('scroll', () => this.#calculateMenuPosition(), abortOptions);
1072
- window?.addEventListener('resize', () => this.#calculateMenuPosition(), abortOptions);
1074
+ scrollableParent.addEventListener('scroll', () => this.#calculateMenuPosition(), {
1075
+ signal: this.openAbort?.signal,
1076
+ });
1077
+ window?.addEventListener('resize', () => this.#calculateMenuPosition(), {
1078
+ signal: this.openAbort?.signal,
1079
+ });
1073
1080
  this.#calculateMenuPosition();
1074
1081
  });
1075
1082
  }
1076
1083
  }
1077
1084
  else {
1078
- popoverEl.hidePopover && popoverEl.hidePopover();
1079
- this.openAbort?.abort();
1080
1085
  this.closed.emit();
1086
+ this.openAbort?.abort();
1087
+ this.openAbort = null;
1081
1088
  }
1082
1089
  });
1083
1090
  }, ...(ngDevMode ? [{ debugName: "openEffect" }] : []));
1084
1091
  }
1085
1092
  #document;
1086
- #BASE_SPACE;
1087
1093
  toggleIsOpen(event) {
1088
1094
  if (!this.disableOpenByClick()) {
1089
1095
  event.preventDefault();
@@ -1092,12 +1098,8 @@ class ShipPopoverComponent {
1092
1098
  }
1093
1099
  }
1094
1100
  eventClose($event) {
1095
- // console.log('eventClose before', $event);
1096
1101
  if (!this.isOpen())
1097
1102
  return;
1098
- // console.log('eventClose after', $event);
1099
- // $event.stopPropagation();
1100
- // $event.preventDefault();
1101
1103
  this.isOpen.set(false);
1102
1104
  }
1103
1105
  #findScrollableParent(element) {
@@ -1111,41 +1113,68 @@ class ShipPopoverComponent {
1111
1113
  }
1112
1114
  return this.#document.documentElement;
1113
1115
  }
1116
+ #alignLeftUnder(triggerRect) {
1117
+ const newLeft = triggerRect.left;
1118
+ const newTop = triggerRect.bottom + BASE_SPACE;
1119
+ return {
1120
+ left: newLeft,
1121
+ top: newTop,
1122
+ };
1123
+ }
1124
+ #alignTopRight(triggerRect) {
1125
+ const newLeft = triggerRect.right + BASE_SPACE;
1126
+ const newTop = triggerRect.top;
1127
+ return {
1128
+ left: newLeft,
1129
+ top: newTop,
1130
+ };
1131
+ }
1132
+ #alignBottomRight(triggerRect) {
1133
+ const newLeft = triggerRect.right + BASE_SPACE;
1134
+ const newTop = triggerRect.bottom;
1135
+ return {
1136
+ left: newLeft,
1137
+ top: newTop,
1138
+ };
1139
+ }
1140
+ #alignLeftOver(triggerRect) {
1141
+ const newLeft = triggerRect.left;
1142
+ const newTop = triggerRect.bottom - triggerRect.height - BASE_SPACE;
1143
+ return {
1144
+ left: newLeft,
1145
+ top: newTop,
1146
+ };
1147
+ }
1114
1148
  #calculateMenuPosition() {
1115
1149
  const triggerRect = this.triggerRef()?.nativeElement.getBoundingClientRect();
1116
- const menuRect = this.popoverRef()?.nativeElement.getBoundingClientRect();
1117
- if (!menuRect)
1118
- return;
1119
- const actionLeftInViewport = triggerRect.left;
1120
- const actionBottomInViewport = triggerRect.bottom;
1121
- let newLeft = actionLeftInViewport;
1122
- let newTop = actionBottomInViewport + this.#BASE_SPACE;
1123
- const outOfBoundsRight = newLeft + menuRect.width > window?.innerWidth;
1124
- const outOfBoundsBottom = newTop + menuRect.height > window?.innerHeight;
1125
- if (!this.SUPPORTS_ANCHOR) {
1126
- newLeft = actionLeftInViewport;
1127
- newTop = actionBottomInViewport + this.#BASE_SPACE;
1128
- if (outOfBoundsBottom) {
1129
- const _newTop = triggerRect.top - menuRect.height - this.#BASE_SPACE;
1130
- const outOfBoundsTop = _newTop < 0;
1131
- if (!outOfBoundsTop)
1132
- newTop = _newTop;
1133
- }
1134
- if (outOfBoundsRight) {
1135
- newLeft = triggerRect.right - menuRect.width;
1136
- if (newLeft < 0) {
1137
- newLeft = 0;
1138
- }
1150
+ const menuRect = this.popoverContentRef()?.nativeElement.getBoundingClientRect();
1151
+ const tryOrderMultiLayer = [this.#alignTopRight, this.#alignBottomRight];
1152
+ const tryOrderDefault = [this.#alignLeftUnder, this.#alignLeftOver];
1153
+ const tryOrder = this.asMultiLayer() ? tryOrderMultiLayer : tryOrderDefault;
1154
+ for (let i = 0; i < tryOrder.length; i++) {
1155
+ const position = tryOrder[i](triggerRect);
1156
+ const outOfBoundsRight = position.left + (menuRect?.width || 0) > window.innerWidth;
1157
+ const outOfBoundsBottom = position.top + (menuRect?.height || 0) > window.innerHeight;
1158
+ if (!outOfBoundsRight && !outOfBoundsBottom) {
1159
+ this.menuStyle.set({
1160
+ left: position.left + 'px',
1161
+ top: position.top + 'px',
1162
+ });
1163
+ return;
1139
1164
  }
1140
- const style = {
1141
- left: newLeft + 'px',
1142
- top: newTop + 'px',
1143
- };
1144
- this.menuStyle.set(style);
1145
1165
  }
1166
+ const fallbackPosition = tryOrder[0](triggerRect);
1167
+ this.menuStyle.set({
1168
+ left: fallbackPosition.left + 'px',
1169
+ top: fallbackPosition.top + 'px',
1170
+ });
1171
+ }
1172
+ ngOnDestroy() {
1173
+ this.openAbort?.abort();
1174
+ this.openAbort = null;
1146
1175
  }
1147
1176
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: ShipPopoverComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1148
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.0", 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: `
1177
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.0", 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 }, { propertyName: "popoverContentRef", first: true, predicate: ["popoverContentRef"], descendants: true, isSignal: true }], ngImport: i0, template: `
1149
1178
  <div class="trigger" #triggerRef [attr.popovertarget]="id() + 'hello'" (click)="toggleIsOpen($event)">
1150
1179
  <div class="trigger-wrapper">
1151
1180
  <ng-content select="[trigger]" />
@@ -1158,7 +1187,7 @@ class ShipPopoverComponent {
1158
1187
  @if (isOpen()) {
1159
1188
  <div [attr.id]="id() + 'hello'" popover="manual" #popoverRef class="popover">
1160
1189
  <div class="overlay" (click)="eventClose($event)"></div>
1161
- <div class="popover-content" [style.position-anchor]="id()" [style]="menuStyle()">
1190
+ <div class="popover-content" #popoverContentRef [style.position-anchor]="id()" [style]="menuStyle()">
1162
1191
  <ng-content />
1163
1192
  </div>
1164
1193
  </div>
@@ -1183,7 +1212,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.0", ngImpor
1183
1212
  @if (isOpen()) {
1184
1213
  <div [attr.id]="id() + 'hello'" popover="manual" #popoverRef class="popover">
1185
1214
  <div class="overlay" (click)="eventClose($event)"></div>
1186
- <div class="popover-content" [style.position-anchor]="id()" [style]="menuStyle()">
1215
+ <div class="popover-content" #popoverContentRef [style.position-anchor]="id()" [style]="menuStyle()">
1187
1216
  <ng-content />
1188
1217
  </div>
1189
1218
  </div>
@@ -1253,7 +1282,6 @@ class ShipFormFieldPopoverComponent {
1253
1282
 
1254
1283
  <sh-popover
1255
1284
  [(isOpen)]="isOpen"
1256
- [disableOpenByClick]="true"
1257
1285
  (closed)="close()"
1258
1286
  [options]="{
1259
1287
  closeOnButton: false,
@@ -1300,7 +1328,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.0", ngImpor
1300
1328
 
1301
1329
  <sh-popover
1302
1330
  [(isOpen)]="isOpen"
1303
- [disableOpenByClick]="true"
1304
1331
  (closed)="close()"
1305
1332
  [options]="{
1306
1333
  closeOnButton: false,
@@ -1687,7 +1714,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.0", ngImpor
1687
1714
 
1688
1715
  class ShipDatepickerInputComponent {
1689
1716
  constructor() {
1690
- this.#INIT_DATE = this.#getUTCDate(new Date());
1717
+ // #INIT_DATE = this.#getUTCDate(new Date());
1691
1718
  this.ngModels = contentChild(NgModel, ...(ngDevMode ? [{ debugName: "ngModels" }] : []));
1692
1719
  this.#datePipe = inject(DatePipe);
1693
1720
  this.#inputRef = signal(null, ...(ngDevMode ? [{ debugName: "#inputRef" }] : []));
@@ -1702,7 +1729,7 @@ class ShipDatepickerInputComponent {
1702
1729
  return null;
1703
1730
  return this.#datePipe.transform(date, mask);
1704
1731
  }, ...(ngDevMode ? [{ debugName: "_maskedDate" }] : []));
1705
- this.internalDate = signal(this.#INIT_DATE, ...(ngDevMode ? [{ debugName: "internalDate" }] : []));
1732
+ this.internalDate = signal(null, ...(ngDevMode ? [{ debugName: "internalDate" }] : []));
1706
1733
  this.isOpen = model(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : []));
1707
1734
  this.currentClass = classMutationSignal();
1708
1735
  this.#inputObserver = contentProjectionSignal('#input-wrap input');
@@ -1728,7 +1755,6 @@ class ShipDatepickerInputComponent {
1728
1755
  }
1729
1756
  }, ...(ngDevMode ? [{ debugName: "#inputRefEffect" }] : []));
1730
1757
  }
1731
- #INIT_DATE;
1732
1758
  #datePipe;
1733
1759
  #inputRef;
1734
1760
  #inputObserver;
@@ -1740,10 +1766,6 @@ class ShipDatepickerInputComponent {
1740
1766
  input.dispatchEvent(new Event('input'));
1741
1767
  }
1742
1768
  }
1743
- open($event) {
1744
- $event.stopPropagation();
1745
- this.isOpen.set(true);
1746
- }
1747
1769
  close() {
1748
1770
  this.closed.emit(this.internalDate());
1749
1771
  }
@@ -1778,7 +1800,7 @@ class ShipDatepickerInputComponent {
1778
1800
  }
1779
1801
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: ShipDatepickerInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1780
1802
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.0", type: ShipDatepickerInputComponent, isStandalone: true, selector: "sh-datepicker-input", inputs: { masking: { classPropertyName: "masking", publicName: "masking", isSignal: true, isRequired: false, transformFunction: null }, isOpen: { classPropertyName: "isOpen", publicName: "isOpen", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closed: "closed", isOpen: "isOpenChange" }, providers: [DatePipe], queries: [{ propertyName: "ngModels", first: true, predicate: NgModel, descendants: true, isSignal: true }], ngImport: i0, template: `
1781
- <sh-form-field-popover (click)="open($event)" (closed)="close()" [(isOpen)]="isOpen">
1803
+ <sh-form-field-popover (closed)="close()" [(isOpen)]="isOpen">
1782
1804
  <ng-content select="label" ngProjectAs="label" />
1783
1805
 
1784
1806
  <ng-content select="[prefix]" ngProjectAs="[prefix]" />
@@ -1786,7 +1808,7 @@ class ShipDatepickerInputComponent {
1786
1808
 
1787
1809
  <div id="input-wrap" class="input" ngProjectAs="input">
1788
1810
  @if (this.masking()) {
1789
- <div class="masked-value" (click)="open($event)">
1811
+ <div class="masked-value">
1790
1812
  {{ _maskedDate() }}
1791
1813
  </div>
1792
1814
  }
@@ -1814,7 +1836,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.0", ngImpor
1814
1836
  imports: [ShipDatepickerComponent, ShipFormFieldPopoverComponent, ShipIconComponent],
1815
1837
  providers: [DatePipe],
1816
1838
  template: `
1817
- <sh-form-field-popover (click)="open($event)" (closed)="close()" [(isOpen)]="isOpen">
1839
+ <sh-form-field-popover (closed)="close()" [(isOpen)]="isOpen">
1818
1840
  <ng-content select="label" ngProjectAs="label" />
1819
1841
 
1820
1842
  <ng-content select="[prefix]" ngProjectAs="[prefix]" />
@@ -1822,7 +1844,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.0", ngImpor
1822
1844
 
1823
1845
  <div id="input-wrap" class="input" ngProjectAs="input">
1824
1846
  @if (this.masking()) {
1825
- <div class="masked-value" (click)="open($event)">
1847
+ <div class="masked-value">
1826
1848
  {{ _maskedDate() }}
1827
1849
  </div>
1828
1850
  }
@@ -1939,10 +1961,6 @@ class ShipDaterangeInputComponent {
1939
1961
  input.dispatchEvent(new Event('input', { bubbles: true }));
1940
1962
  input.dispatchEvent(new Event('change', { bubbles: true }));
1941
1963
  }
1942
- open($event) {
1943
- $event.stopPropagation();
1944
- this.isOpen.set(true);
1945
- }
1946
1964
  close() {
1947
1965
  this.closed.emit({
1948
1966
  start: this.startDate(),
@@ -1951,11 +1969,7 @@ class ShipDaterangeInputComponent {
1951
1969
  }
1952
1970
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: ShipDaterangeInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1953
1971
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.0", type: ShipDaterangeInputComponent, isStandalone: true, selector: "sh-daterange-input", inputs: { monthsToShow: { classPropertyName: "monthsToShow", publicName: "monthsToShow", isSignal: true, isRequired: false, transformFunction: null }, masking: { classPropertyName: "masking", publicName: "masking", isSignal: true, isRequired: false, transformFunction: null }, isOpen: { classPropertyName: "isOpen", publicName: "isOpen", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closed: "closed", isOpen: "isOpenChange" }, providers: [DatePipe], queries: [{ propertyName: "startDateInputs", predicate: ["startDate"], isSignal: true }, { propertyName: "endDateInputs", predicate: ["endDate"], isSignal: true }], ngImport: i0, template: `
1954
- <sh-form-field-popover
1955
- [class]="'columns-' + monthsToShow()"
1956
- (click)="open($event)"
1957
- (closed)="close()"
1958
- [(isOpen)]="isOpen">
1972
+ <sh-form-field-popover [class]="'columns-' + monthsToShow()" (closed)="close()" [(isOpen)]="isOpen">
1959
1973
  <ng-content select="label" ngProjectAs="label" />
1960
1974
 
1961
1975
  <ng-content select="[prefix]" ngProjectAs="[prefix]" />
@@ -1963,9 +1977,7 @@ class ShipDaterangeInputComponent {
1963
1977
 
1964
1978
  <div class="input" ngProjectAs="input" #inputWrap>
1965
1979
  @if (this.masking()) {
1966
- <div class="masked-value" (click)="open($event)">
1967
- {{ _maskedStartDate() ?? 'N/A' }} - {{ _maskedEndDate() ?? 'N/A' }}
1968
- </div>
1980
+ <div class="masked-value">{{ _maskedStartDate() ?? 'N/A' }} - {{ _maskedEndDate() ?? 'N/A' }}</div>
1969
1981
  }
1970
1982
  <ng-content select="input" />
1971
1983
  </div>
@@ -1996,11 +2008,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.0", ngImpor
1996
2008
  imports: [ShipDatepickerComponent, ShipFormFieldPopoverComponent, ShipIconComponent],
1997
2009
  providers: [DatePipe],
1998
2010
  template: `
1999
- <sh-form-field-popover
2000
- [class]="'columns-' + monthsToShow()"
2001
- (click)="open($event)"
2002
- (closed)="close()"
2003
- [(isOpen)]="isOpen">
2011
+ <sh-form-field-popover [class]="'columns-' + monthsToShow()" (closed)="close()" [(isOpen)]="isOpen">
2004
2012
  <ng-content select="label" ngProjectAs="label" />
2005
2013
 
2006
2014
  <ng-content select="[prefix]" ngProjectAs="[prefix]" />
@@ -2008,9 +2016,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.0", ngImpor
2008
2016
 
2009
2017
  <div class="input" ngProjectAs="input" #inputWrap>
2010
2018
  @if (this.masking()) {
2011
- <div class="masked-value" (click)="open($event)">
2012
- {{ _maskedStartDate() ?? 'N/A' }} - {{ _maskedEndDate() ?? 'N/A' }}
2013
- </div>
2019
+ <div class="masked-value">{{ _maskedStartDate() ?? 'N/A' }} - {{ _maskedEndDate() ?? 'N/A' }}</div>
2014
2020
  }
2015
2021
  <ng-content select="input" />
2016
2022
  </div>