@ship-ui/core 0.15.14 → 0.15.15

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.
@@ -1038,56 +1038,66 @@ class ShipPopoverComponent {
1038
1038
  ...this.options(),
1039
1039
  }), ...(ngDevMode ? [{ debugName: "defaultOptionMerge" }] : []));
1040
1040
  this.triggerRef = viewChild.required('triggerRef');
1041
- this.popoverRef = viewChild.required('popoverRef');
1041
+ this.popoverRef = viewChild('popoverRef', ...(ngDevMode ? [{ debugName: "popoverRef" }] : []));
1042
1042
  this.id = signal('--' + generateUniqueId(), ...(ngDevMode ? [{ debugName: "id" }] : []));
1043
1043
  this.menuStyle = signal(null, ...(ngDevMode ? [{ debugName: "menuStyle" }] : []));
1044
1044
  this.openAbort = null;
1045
1045
  this.openEffect = effect(() => {
1046
- const popoverEl = this.popoverRef()?.nativeElement;
1047
1046
  const open = this.isOpen();
1048
- if (open) {
1049
- if (this.openAbort) {
1050
- this.openAbort.abort();
1051
- }
1052
- this.openAbort = new AbortController();
1053
- const abortOptions = {
1054
- signal: this.openAbort?.signal,
1055
- };
1056
- popoverEl?.showPopover();
1057
- this.#document.addEventListener('keydown', (e) => {
1058
- if (e.key === 'Escape' && !this.defaultOptionMerge().closeOnEsc) {
1059
- e.preventDefault();
1047
+ queueMicrotask(() => {
1048
+ const popoverEl = this.popoverRef()?.nativeElement;
1049
+ if (!popoverEl)
1050
+ return;
1051
+ if (open) {
1052
+ if (this.openAbort) {
1053
+ this.openAbort.abort();
1060
1054
  }
1061
- if (e.key === 'Escape' && this.defaultOptionMerge().closeOnEsc) {
1062
- this.isOpen.set(false);
1055
+ this.openAbort = new AbortController();
1056
+ const abortOptions = {
1057
+ signal: this.openAbort?.signal,
1058
+ };
1059
+ this.#document.addEventListener('keydown', (e) => {
1060
+ if (e.key === 'Escape' && !this.defaultOptionMerge().closeOnEsc) {
1061
+ e.preventDefault();
1062
+ }
1063
+ if (e.key === 'Escape' && this.defaultOptionMerge().closeOnEsc) {
1064
+ this.isOpen.set(false);
1065
+ }
1066
+ }, abortOptions);
1067
+ popoverEl.showPopover();
1068
+ if (!this.SUPPORTS_ANCHOR) {
1069
+ setTimeout(() => {
1070
+ const scrollableParent = this.#findScrollableParent(popoverEl);
1071
+ scrollableParent.addEventListener('scroll', () => this.#calculateMenuPosition(), abortOptions);
1072
+ window?.addEventListener('resize', () => this.#calculateMenuPosition(), abortOptions);
1073
+ this.#calculateMenuPosition();
1074
+ });
1063
1075
  }
1064
- }, abortOptions);
1065
- setTimeout(() => {
1066
- const scrollableParent = this.#findScrollableParent(this.popoverRef()?.nativeElement);
1067
- scrollableParent.addEventListener('scroll', () => this.#calculateMenuPosition(), abortOptions);
1068
- window?.addEventListener('resize', () => this.#calculateMenuPosition(), abortOptions);
1069
- this.#calculateMenuPosition();
1070
- });
1071
- }
1072
- else {
1073
- popoverEl.hidePopover && popoverEl.hidePopover();
1074
- this.openAbort?.abort();
1075
- this.closed.emit();
1076
- }
1076
+ }
1077
+ else {
1078
+ popoverEl.hidePopover && popoverEl.hidePopover();
1079
+ this.openAbort?.abort();
1080
+ this.closed.emit();
1081
+ }
1082
+ });
1077
1083
  }, ...(ngDevMode ? [{ debugName: "openEffect" }] : []));
1078
1084
  }
1079
1085
  #document;
1080
1086
  #BASE_SPACE;
1081
1087
  toggleIsOpen(event) {
1082
- event.preventDefault();
1083
- event.stopPropagation();
1084
1088
  if (!this.disableOpenByClick()) {
1089
+ event.preventDefault();
1090
+ event.stopPropagation();
1085
1091
  this.isOpen.set(!this.isOpen());
1086
1092
  }
1087
1093
  }
1088
1094
  eventClose($event) {
1089
- $event.stopPropagation();
1090
- $event.preventDefault();
1095
+ // console.log('eventClose before', $event);
1096
+ if (!this.isOpen())
1097
+ return;
1098
+ // console.log('eventClose after', $event);
1099
+ // $event.stopPropagation();
1100
+ // $event.preventDefault();
1091
1101
  this.isOpen.set(false);
1092
1102
  }
1093
1103
  #findScrollableParent(element) {
@@ -1104,6 +1114,8 @@ class ShipPopoverComponent {
1104
1114
  #calculateMenuPosition() {
1105
1115
  const triggerRect = this.triggerRef()?.nativeElement.getBoundingClientRect();
1106
1116
  const menuRect = this.popoverRef()?.nativeElement.getBoundingClientRect();
1117
+ if (!menuRect)
1118
+ return;
1107
1119
  const actionLeftInViewport = triggerRect.left;
1108
1120
  const actionBottomInViewport = triggerRect.bottom;
1109
1121
  let newLeft = actionLeftInViewport;
@@ -1133,8 +1145,8 @@ class ShipPopoverComponent {
1133
1145
  }
1134
1146
  }
1135
1147
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: ShipPopoverComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1136
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.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: `
1137
- <div class="trigger" #triggerRef (click)="toggleIsOpen($event)">
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: `
1149
+ <div class="trigger" #triggerRef [attr.popovertarget]="id() + 'hello'" (click)="toggleIsOpen($event)">
1138
1150
  <div class="trigger-wrapper">
1139
1151
  <ng-content select="[trigger]" />
1140
1152
  <ng-content select="button" />
@@ -1143,10 +1155,14 @@ class ShipPopoverComponent {
1143
1155
  <div class="trigger-anchor" [style.anchor-name]="id()"></div>
1144
1156
  </div>
1145
1157
 
1146
- <div popover #popoverRef class="popover" [style.position-anchor]="id()" [style]="menuStyle()">
1147
- <div class="overlay" (click)="isOpen() && eventClose($event)"></div>
1148
- <ng-content />
1149
- </div>
1158
+ @if (isOpen()) {
1159
+ <div [attr.id]="id() + 'hello'" popover="manual" #popoverRef class="popover">
1160
+ <div class="overlay" (click)="eventClose($event)"></div>
1161
+ <div class="popover-content" [style.position-anchor]="id()" [style]="menuStyle()">
1162
+ <ng-content />
1163
+ </div>
1164
+ </div>
1165
+ }
1150
1166
  `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1151
1167
  }
1152
1168
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: ShipPopoverComponent, decorators: [{
@@ -1155,7 +1171,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.0", ngImpor
1155
1171
  selector: 'sh-popover',
1156
1172
  imports: [],
1157
1173
  template: `
1158
- <div class="trigger" #triggerRef (click)="toggleIsOpen($event)">
1174
+ <div class="trigger" #triggerRef [attr.popovertarget]="id() + 'hello'" (click)="toggleIsOpen($event)">
1159
1175
  <div class="trigger-wrapper">
1160
1176
  <ng-content select="[trigger]" />
1161
1177
  <ng-content select="button" />
@@ -1164,10 +1180,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.0", ngImpor
1164
1180
  <div class="trigger-anchor" [style.anchor-name]="id()"></div>
1165
1181
  </div>
1166
1182
 
1167
- <div popover #popoverRef class="popover" [style.position-anchor]="id()" [style]="menuStyle()">
1168
- <div class="overlay" (click)="isOpen() && eventClose($event)"></div>
1169
- <ng-content />
1170
- </div>
1183
+ @if (isOpen()) {
1184
+ <div [attr.id]="id() + 'hello'" popover="manual" #popoverRef class="popover">
1185
+ <div class="overlay" (click)="eventClose($event)"></div>
1186
+ <div class="popover-content" [style.position-anchor]="id()" [style]="menuStyle()">
1187
+ <ng-content />
1188
+ </div>
1189
+ </div>
1190
+ }
1171
1191
  `,
1172
1192
  changeDetection: ChangeDetectionStrategy.OnPush,
1173
1193
  host: {
@@ -2513,7 +2533,7 @@ class ShipMenuComponent {
2513
2533
  this.closed = output();
2514
2534
  this.searchable = input(false, ...(ngDevMode ? [{ debugName: "searchable" }] : []));
2515
2535
  this.activeOptionIndex = signal(-1, ...(ngDevMode ? [{ debugName: "activeOptionIndex" }] : []));
2516
- this.inputRef = viewChild('input', ...(ngDevMode ? [{ debugName: "inputRef" }] : []));
2536
+ this.inputRef = viewChild('inputRef', ...(ngDevMode ? [{ debugName: "inputRef" }] : []));
2517
2537
  this.optionsRef = viewChild('optionsRef', ...(ngDevMode ? [{ debugName: "optionsRef" }] : []));
2518
2538
  this.options = observeChildren(this.optionsRef, this.customOptionElementSelectors);
2519
2539
  this.optionsEl = computed(() => this.options.signal().filter((x) => !x.disabled), ...(ngDevMode ? [{ debugName: "optionsEl" }] : []));
@@ -2616,6 +2636,16 @@ class ShipMenuComponent {
2616
2636
  }, ...(ngDevMode ? [{ debugName: "activeOptionIndexEffect" }] : []));
2617
2637
  }
2618
2638
  #renderer;
2639
+ toggleIsOpen(event) {
2640
+ event.preventDefault();
2641
+ event.stopPropagation();
2642
+ if (this.disabled())
2643
+ return;
2644
+ this.isOpen.set(!this.isOpen());
2645
+ if (this.searchable() && this.isOpen()) {
2646
+ setTimeout(() => this.inputRef()?.nativeElement.focus());
2647
+ }
2648
+ }
2619
2649
  #calculateMatchScore(option, input) {
2620
2650
  if (!input)
2621
2651
  return 0;
@@ -2709,7 +2739,7 @@ class ShipMenuComponent {
2709
2739
  }
2710
2740
  }
2711
2741
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: ShipMenuComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2712
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.0", type: ShipMenuComponent, isStandalone: true, selector: "sh-menu", inputs: { asMultiLayer: { classPropertyName: "asMultiLayer", publicName: "asMultiLayer", isSignal: true, isRequired: false, transformFunction: null }, openIndicator: { classPropertyName: "openIndicator", publicName: "openIndicator", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, customOptionElementSelectors: { classPropertyName: "customOptionElementSelectors", publicName: "customOptionElementSelectors", isSignal: true, isRequired: false, transformFunction: null }, keepClickedOptionActive: { classPropertyName: "keepClickedOptionActive", publicName: "keepClickedOptionActive", isSignal: true, isRequired: false, transformFunction: null }, closeOnClick: { classPropertyName: "closeOnClick", publicName: "closeOnClick", isSignal: true, isRequired: false, transformFunction: null }, isOpen: { classPropertyName: "isOpen", publicName: "isOpen", isSignal: true, isRequired: false, transformFunction: null }, searchable: { classPropertyName: "searchable", publicName: "searchable", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { isOpen: "isOpenChange", closed: "closed" }, host: { properties: { "class.disabled": "disabled()", "class.has-search": "searchable()", "class.multi-layer": "asMultiLayer()" } }, viewQueries: [{ propertyName: "inputRef", first: true, predicate: ["input"], descendants: true, isSignal: true }, { propertyName: "optionsRef", first: true, predicate: ["optionsRef"], descendants: true, isSignal: true }], ngImport: i0, template: `
2742
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.0", type: ShipMenuComponent, isStandalone: true, selector: "sh-menu", inputs: { asMultiLayer: { classPropertyName: "asMultiLayer", publicName: "asMultiLayer", isSignal: true, isRequired: false, transformFunction: null }, openIndicator: { classPropertyName: "openIndicator", publicName: "openIndicator", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, customOptionElementSelectors: { classPropertyName: "customOptionElementSelectors", publicName: "customOptionElementSelectors", isSignal: true, isRequired: false, transformFunction: null }, keepClickedOptionActive: { classPropertyName: "keepClickedOptionActive", publicName: "keepClickedOptionActive", isSignal: true, isRequired: false, transformFunction: null }, closeOnClick: { classPropertyName: "closeOnClick", publicName: "closeOnClick", isSignal: true, isRequired: false, transformFunction: null }, isOpen: { classPropertyName: "isOpen", publicName: "isOpen", isSignal: true, isRequired: false, transformFunction: null }, searchable: { classPropertyName: "searchable", publicName: "searchable", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { isOpen: "isOpenChange", closed: "closed" }, host: { properties: { "class.disabled": "disabled()", "class.has-search": "searchable()", "class.multi-layer": "asMultiLayer()" } }, viewQueries: [{ propertyName: "inputRef", first: true, predicate: ["inputRef"], descendants: true, isSignal: true }, { propertyName: "optionsRef", first: true, predicate: ["optionsRef"], descendants: true, isSignal: true }], ngImport: i0, template: `
2713
2743
  <sh-popover
2714
2744
  #formFieldWrapper
2715
2745
  [(isOpen)]="isOpen"
@@ -2720,7 +2750,7 @@ class ShipMenuComponent {
2720
2750
  closeOnButton: false,
2721
2751
  closeOnEsc: true,
2722
2752
  }">
2723
- <div trigger [class.is-open]="isOpen()" (click)="!disabled() && isOpen.set(true)">
2753
+ <div trigger [class.is-open]="isOpen()" (click)="toggleIsOpen($event)">
2724
2754
  <ng-content />
2725
2755
 
2726
2756
  @if (openIndicator()) {
@@ -2730,7 +2760,7 @@ class ShipMenuComponent {
2730
2760
 
2731
2761
  <div class="form-field-wrap">
2732
2762
  <sh-form-field class="small stretch" [class.hidden]="searchable() === false">
2733
- <input type="text" #input placeholder="Search" />
2763
+ <input type="text" #inputRef placeholder="Search" />
2734
2764
  </sh-form-field>
2735
2765
  </div>
2736
2766
 
@@ -2760,7 +2790,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.0", ngImpor
2760
2790
  closeOnButton: false,
2761
2791
  closeOnEsc: true,
2762
2792
  }">
2763
- <div trigger [class.is-open]="isOpen()" (click)="!disabled() && isOpen.set(true)">
2793
+ <div trigger [class.is-open]="isOpen()" (click)="toggleIsOpen($event)">
2764
2794
  <ng-content />
2765
2795
 
2766
2796
  @if (openIndicator()) {
@@ -2770,7 +2800,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.0", ngImpor
2770
2800
 
2771
2801
  <div class="form-field-wrap">
2772
2802
  <sh-form-field class="small stretch" [class.hidden]="searchable() === false">
2773
- <input type="text" #input placeholder="Search" />
2803
+ <input type="text" #inputRef placeholder="Search" />
2774
2804
  </sh-form-field>
2775
2805
  </div>
2776
2806