@ship-ui/core 0.17.14 → 0.17.16
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.
|
@@ -1061,6 +1061,12 @@
|
|
|
1061
1061
|
],
|
|
1062
1062
|
"outputs": [],
|
|
1063
1063
|
"methods": [
|
|
1064
|
+
{
|
|
1065
|
+
"name": "cancelAnimationFrame",
|
|
1066
|
+
"parameters": "this.rafId);\n }\n this.rafId = requestAnimationFrame(this.calculateTooltipPosition);\n };\n\n private calculateTooltipPosition = (",
|
|
1067
|
+
"returnType": "void =>",
|
|
1068
|
+
"description": ""
|
|
1069
|
+
},
|
|
1064
1070
|
{
|
|
1065
1071
|
"name": "untracked",
|
|
1066
1072
|
"parameters": "() => {\n if (this.isOpen() && openRef?.component === this && openRef?.wrapperComponentRef",
|
|
@@ -3201,12 +3207,24 @@
|
|
|
3201
3207
|
}
|
|
3202
3208
|
],
|
|
3203
3209
|
"methods": [
|
|
3210
|
+
{
|
|
3211
|
+
"name": "onCleanup",
|
|
3212
|
+
"parameters": "() => {\n const index = ShipMenu.openMenus.indexOf(this);\n if (index > -1",
|
|
3213
|
+
"returnType": "any",
|
|
3214
|
+
"description": ""
|
|
3215
|
+
},
|
|
3204
3216
|
{
|
|
3205
3217
|
"name": "toggleIsOpen",
|
|
3206
3218
|
"parameters": "event: MouseEvent",
|
|
3207
3219
|
"returnType": "any",
|
|
3208
3220
|
"description": ""
|
|
3209
3221
|
},
|
|
3222
|
+
{
|
|
3223
|
+
"name": "open",
|
|
3224
|
+
"parameters": "",
|
|
3225
|
+
"returnType": "any",
|
|
3226
|
+
"description": ""
|
|
3227
|
+
},
|
|
3210
3228
|
{
|
|
3211
3229
|
"name": "nextActiveIndex",
|
|
3212
3230
|
"parameters": "activeIndex: number",
|
|
@@ -3240,7 +3258,7 @@
|
|
|
3240
3258
|
},
|
|
3241
3259
|
{
|
|
3242
3260
|
"name": "search-menu-example",
|
|
3243
|
-
"html": "<sh-menu [searchable]=\"true\">\n <button shButton class=\"outlined\">Open searchable menu</button>\n <ng-container menu>\n @for (item of filteredItems; track item.value) {\n <button (click)=\"select(item)\" [class.selected]=\"selected === item.value\">\n <p>\n hello world\n <br />\n {{ item.label }}\n </p>\n </button>\n }\n </ng-container>\n</sh-menu>\n",
|
|
3261
|
+
"html": "<sh-menu [searchable]=\"true\">\n <button shButton class=\"outlined\">Open searchable menu</button>\n <ng-container menu>\n @for (item of filteredItems; track item.value) {\n <button (click)=\"select(item)\" [class.selected]=\"selected === item.value\">\n <p>\n hello world\n <br />\n {{ item.label }}\n </p>\n </button>\n }\n </ng-container>\n</sh-menu>\n\n<sh-menu [searchable]=\"true\">\n <button shButton class=\"outlined\">Open searchable menu</button>\n <ng-container menu>\n @for (item of filteredItems; track item.value) {\n <button (click)=\"select(item)\" [class.selected]=\"selected === item.value\">\n <div class=\"option-col\">\n {{ item.label }} asdlkjadskljjkladsjkldaljkdaslkjad jklsjkl dasjkld as\n <p>hello world but im extra long so i should wrap to the next line</p>\n </div>\n </button>\n }\n </ng-container>\n</sh-menu>\n",
|
|
3244
3262
|
"ts": "import { Component } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { ShipButton, ShipMenu } from 'ship-ui';\n\n@Component({\n selector: 'sh-search-menu-example',\n templateUrl: './search-menu-example.html',\n styleUrls: ['./search-menu-example.scss'],\n imports: [FormsModule, ShipMenu, ShipButton],\n standalone: true,\n})\nexport class SearchMenuExample {\n menuItems = [\n { label: 'Dashboard', value: 'dashboard' },\n { label: 'Users', value: 'users' },\n { label: 'Settings', value: 'settings' },\n { label: 'Billing', value: 'billing' },\n { label: 'Support', value: 'support' },\n ];\n search = '';\n selected: string | null = null;\n\n get filteredItems() {\n return this.menuItems.filter((item) => item.label.toLowerCase().includes(this.search.toLowerCase()));\n }\n\n select(item: any) {\n this.selected = item.value;\n }\n}\n"
|
|
3245
3263
|
},
|
|
3246
3264
|
{
|
|
@@ -2663,6 +2663,8 @@ class ShipPopover {
|
|
|
2663
2663
|
}, {
|
|
2664
2664
|
signal: this.openAbort?.signal,
|
|
2665
2665
|
});
|
|
2666
|
+
if (!popoverEl.isConnected)
|
|
2667
|
+
return;
|
|
2666
2668
|
popoverEl.showPopover();
|
|
2667
2669
|
if (!this.SUPPORTS_ANCHOR) {
|
|
2668
2670
|
setTimeout(() => {
|
|
@@ -3840,9 +3842,22 @@ class ShipMenu {
|
|
|
3840
3842
|
this.activeOptionIndex = signal(-1, ...(ngDevMode ? [{ debugName: "activeOptionIndex" }] : []));
|
|
3841
3843
|
this.inputRef = viewChild('inputRef', ...(ngDevMode ? [{ debugName: "inputRef" }] : []));
|
|
3842
3844
|
this.optionsRef = viewChild('optionsRef', ...(ngDevMode ? [{ debugName: "optionsRef" }] : []));
|
|
3845
|
+
this.openMenusEffect = effect((onCleanup) => {
|
|
3846
|
+
if (this.isOpen()) {
|
|
3847
|
+
ShipMenu.openMenus.push(this);
|
|
3848
|
+
}
|
|
3849
|
+
onCleanup(() => {
|
|
3850
|
+
const index = ShipMenu.openMenus.indexOf(this);
|
|
3851
|
+
if (index > -1) {
|
|
3852
|
+
ShipMenu.openMenus.splice(index, 1);
|
|
3853
|
+
}
|
|
3854
|
+
});
|
|
3855
|
+
}, ...(ngDevMode ? [{ debugName: "openMenusEffect" }] : []));
|
|
3843
3856
|
this.options = observeChildren(this.optionsRef, this.customOptionElementSelectors);
|
|
3844
3857
|
this.optionsEl = computed(() => this.options.signal().filter((x) => !x.disabled), ...(ngDevMode ? [{ debugName: "optionsEl" }] : []));
|
|
3845
3858
|
this.inputValue = createFormInputSignal(this.inputRef);
|
|
3859
|
+
this.optionsId = generateUniqueId();
|
|
3860
|
+
this.activeOptionId = signal(undefined, ...(ngDevMode ? [{ debugName: "activeOptionId" }] : []));
|
|
3846
3861
|
this.abortController = null;
|
|
3847
3862
|
this.optionsEffect = effect(() => {
|
|
3848
3863
|
if (this.abortController !== null) {
|
|
@@ -3884,6 +3899,9 @@ class ShipMenu {
|
|
|
3884
3899
|
}
|
|
3885
3900
|
}, ...(ngDevMode ? [{ debugName: "optionsEffect" }] : []));
|
|
3886
3901
|
this.keyDownEventListener = (e) => {
|
|
3902
|
+
// Only handle events if this is the most recently opened menu
|
|
3903
|
+
if (ShipMenu.openMenus.at(-1) !== this)
|
|
3904
|
+
return;
|
|
3887
3905
|
const activeOptionIndex = this.activeOptionIndex();
|
|
3888
3906
|
if (e.key === 'ArrowDown') {
|
|
3889
3907
|
e.preventDefault();
|
|
@@ -3896,8 +3914,20 @@ class ShipMenu {
|
|
|
3896
3914
|
else if (e.key === 'Enter') {
|
|
3897
3915
|
e.preventDefault();
|
|
3898
3916
|
if (activeOptionIndex > -1) {
|
|
3899
|
-
this.activeElements()[activeOptionIndex]
|
|
3900
|
-
|
|
3917
|
+
const el = this.activeElements()[activeOptionIndex];
|
|
3918
|
+
const parent = el.parentElement;
|
|
3919
|
+
// For nested menu's
|
|
3920
|
+
if (parent?.hasAttribute('trigger')) {
|
|
3921
|
+
const event = new CustomEvent('ship-menu-open', {
|
|
3922
|
+
bubbles: true,
|
|
3923
|
+
cancelable: true,
|
|
3924
|
+
});
|
|
3925
|
+
el.dispatchEvent(event);
|
|
3926
|
+
}
|
|
3927
|
+
else {
|
|
3928
|
+
el.click();
|
|
3929
|
+
queueMicrotask(() => this.close('active'));
|
|
3930
|
+
}
|
|
3901
3931
|
}
|
|
3902
3932
|
}
|
|
3903
3933
|
else if (e.key === 'Tab') {
|
|
@@ -3920,6 +3950,10 @@ class ShipMenu {
|
|
|
3920
3950
|
this._lastElementList = allOptions;
|
|
3921
3951
|
for (let i = 0; i < allOptions.length; i++) {
|
|
3922
3952
|
this.#renderer.removeStyle(allOptions[i], 'order');
|
|
3953
|
+
if (!allOptions[i].id) {
|
|
3954
|
+
allOptions[i].id = `${this.optionsId}-option-${i}`;
|
|
3955
|
+
}
|
|
3956
|
+
allOptions[i].setAttribute('role', 'option');
|
|
3923
3957
|
}
|
|
3924
3958
|
return;
|
|
3925
3959
|
}
|
|
@@ -3943,31 +3977,61 @@ class ShipMenu {
|
|
|
3943
3977
|
}
|
|
3944
3978
|
this.activeElements.set(optionElements);
|
|
3945
3979
|
this._lastElementList = optionElements;
|
|
3980
|
+
// Assign IDs to options for ARIA support
|
|
3981
|
+
for (let i = 0; i < optionElements.length; i++) {
|
|
3982
|
+
if (!optionElements[i].id) {
|
|
3983
|
+
optionElements[i].id = `${this.optionsId}-option-${i}`;
|
|
3984
|
+
}
|
|
3985
|
+
optionElements[i].setAttribute('role', 'option');
|
|
3986
|
+
}
|
|
3946
3987
|
}, ...(ngDevMode ? [{ debugName: "inputValueEffect" }] : []));
|
|
3947
3988
|
this.activeOptionIndexEffect = effect(() => {
|
|
3948
3989
|
const optionElements = this.activeElements();
|
|
3949
3990
|
const activeOptionIndex = this.activeOptionIndex();
|
|
3950
3991
|
for (let index = 0; index < optionElements.length; index++) {
|
|
3951
3992
|
optionElements[index].classList.remove('active');
|
|
3993
|
+
optionElements[index].removeAttribute('aria-selected');
|
|
3952
3994
|
}
|
|
3953
3995
|
if (activeOptionIndex > -1) {
|
|
3954
|
-
optionElements[activeOptionIndex]
|
|
3955
|
-
|
|
3996
|
+
const activeOption = optionElements[activeOptionIndex];
|
|
3997
|
+
activeOption.scrollIntoView({ block: 'center' });
|
|
3998
|
+
activeOption.classList.add('active');
|
|
3999
|
+
activeOption.setAttribute('aria-selected', 'true');
|
|
4000
|
+
this.activeOptionId.set(activeOption.id);
|
|
4001
|
+
}
|
|
4002
|
+
else {
|
|
4003
|
+
this.activeOptionId.set(undefined);
|
|
3956
4004
|
}
|
|
3957
4005
|
}, ...(ngDevMode ? [{ debugName: "activeOptionIndexEffect" }] : []));
|
|
3958
4006
|
}
|
|
3959
4007
|
#document;
|
|
3960
4008
|
#renderer;
|
|
4009
|
+
static { this.openMenus = []; }
|
|
3961
4010
|
toggleIsOpen(event) {
|
|
3962
4011
|
event.preventDefault();
|
|
3963
4012
|
event.stopPropagation();
|
|
3964
4013
|
if (this.disabled())
|
|
3965
4014
|
return;
|
|
3966
|
-
|
|
3967
|
-
|
|
4015
|
+
if (this.isOpen()) {
|
|
4016
|
+
this.close('fromPopover');
|
|
4017
|
+
}
|
|
4018
|
+
else {
|
|
4019
|
+
this.open();
|
|
4020
|
+
}
|
|
4021
|
+
}
|
|
4022
|
+
open() {
|
|
4023
|
+
if (this.disabled())
|
|
4024
|
+
return;
|
|
4025
|
+
this.isOpen.set(true);
|
|
4026
|
+
if (this.searchable()) {
|
|
3968
4027
|
setTimeout(() => this.inputRef()?.nativeElement.focus());
|
|
3969
4028
|
}
|
|
3970
4029
|
}
|
|
4030
|
+
onShipMenuOpen(event) {
|
|
4031
|
+
event.preventDefault();
|
|
4032
|
+
event.stopPropagation();
|
|
4033
|
+
this.open();
|
|
4034
|
+
}
|
|
3971
4035
|
#calculateMatchScore(option, input) {
|
|
3972
4036
|
if (!input)
|
|
3973
4037
|
return 0;
|
|
@@ -4052,6 +4116,7 @@ class ShipMenu {
|
|
|
4052
4116
|
const optionElements = this.optionsEl();
|
|
4053
4117
|
for (let index = 0; index < optionElements.length; index++) {
|
|
4054
4118
|
optionElements[index].classList.remove('active');
|
|
4119
|
+
optionElements[index].removeAttribute('aria-selected');
|
|
4055
4120
|
}
|
|
4056
4121
|
}
|
|
4057
4122
|
ngOnDestroy() {
|
|
@@ -4059,9 +4124,13 @@ class ShipMenu {
|
|
|
4059
4124
|
this.abortController.abort();
|
|
4060
4125
|
this.abortController = null;
|
|
4061
4126
|
}
|
|
4127
|
+
const index = ShipMenu.openMenus.indexOf(this);
|
|
4128
|
+
if (index > -1) {
|
|
4129
|
+
ShipMenu.openMenus.splice(index, 1);
|
|
4130
|
+
}
|
|
4062
4131
|
}
|
|
4063
4132
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: ShipMenu, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
4064
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.0", type: ShipMenu, 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: `
|
|
4133
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.0", type: ShipMenu, 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: { listeners: { "ship-menu-open": "onShipMenuOpen($event)" }, 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: `
|
|
4065
4134
|
<sh-popover
|
|
4066
4135
|
#formFieldWrapper
|
|
4067
4136
|
[(isOpen)]="isOpen"
|
|
@@ -4072,7 +4141,15 @@ class ShipMenu {
|
|
|
4072
4141
|
closeOnButton: false,
|
|
4073
4142
|
closeOnEsc: true,
|
|
4074
4143
|
}">
|
|
4075
|
-
<div
|
|
4144
|
+
<div
|
|
4145
|
+
trigger
|
|
4146
|
+
[class.is-open]="isOpen()"
|
|
4147
|
+
(click)="toggleIsOpen($event)"
|
|
4148
|
+
role="combobox"
|
|
4149
|
+
[attr.aria-expanded]="isOpen()"
|
|
4150
|
+
aria-haspopup="listbox"
|
|
4151
|
+
[attr.aria-controls]="optionsId"
|
|
4152
|
+
[attr.aria-activedescendant]="activeOptionId()">
|
|
4076
4153
|
<ng-content />
|
|
4077
4154
|
|
|
4078
4155
|
@if (openIndicator()) {
|
|
@@ -4082,7 +4159,15 @@ class ShipMenu {
|
|
|
4082
4159
|
|
|
4083
4160
|
<div class="form-field-wrap">
|
|
4084
4161
|
<sh-form-field class="small stretch" [class.hidden]="searchable() === false">
|
|
4085
|
-
<input
|
|
4162
|
+
<input
|
|
4163
|
+
type="text"
|
|
4164
|
+
#inputRef
|
|
4165
|
+
placeholder="Search"
|
|
4166
|
+
role="combobox"
|
|
4167
|
+
[attr.aria-expanded]="isOpen()"
|
|
4168
|
+
[attr.aria-controls]="optionsId"
|
|
4169
|
+
[attr.aria-activedescendant]="activeOptionId()"
|
|
4170
|
+
aria-autocomplete="list" />
|
|
4086
4171
|
</sh-form-field>
|
|
4087
4172
|
</div>
|
|
4088
4173
|
|
|
@@ -4090,7 +4175,10 @@ class ShipMenu {
|
|
|
4090
4175
|
class="options"
|
|
4091
4176
|
#optionsRef
|
|
4092
4177
|
(click)="close('active')"
|
|
4093
|
-
[class.searching]="searchable() && inputValue() !== ''"
|
|
4178
|
+
[class.searching]="searchable() && inputValue() !== ''"
|
|
4179
|
+
role="listbox"
|
|
4180
|
+
[id]="optionsId"
|
|
4181
|
+
[attr.aria-activedescendant]="activeOptionId()">
|
|
4094
4182
|
<ng-content select="[menu]" />
|
|
4095
4183
|
</div>
|
|
4096
4184
|
</sh-popover>
|
|
@@ -4112,7 +4200,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImpor
|
|
|
4112
4200
|
closeOnButton: false,
|
|
4113
4201
|
closeOnEsc: true,
|
|
4114
4202
|
}">
|
|
4115
|
-
<div
|
|
4203
|
+
<div
|
|
4204
|
+
trigger
|
|
4205
|
+
[class.is-open]="isOpen()"
|
|
4206
|
+
(click)="toggleIsOpen($event)"
|
|
4207
|
+
role="combobox"
|
|
4208
|
+
[attr.aria-expanded]="isOpen()"
|
|
4209
|
+
aria-haspopup="listbox"
|
|
4210
|
+
[attr.aria-controls]="optionsId"
|
|
4211
|
+
[attr.aria-activedescendant]="activeOptionId()">
|
|
4116
4212
|
<ng-content />
|
|
4117
4213
|
|
|
4118
4214
|
@if (openIndicator()) {
|
|
@@ -4122,7 +4218,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImpor
|
|
|
4122
4218
|
|
|
4123
4219
|
<div class="form-field-wrap">
|
|
4124
4220
|
<sh-form-field class="small stretch" [class.hidden]="searchable() === false">
|
|
4125
|
-
<input
|
|
4221
|
+
<input
|
|
4222
|
+
type="text"
|
|
4223
|
+
#inputRef
|
|
4224
|
+
placeholder="Search"
|
|
4225
|
+
role="combobox"
|
|
4226
|
+
[attr.aria-expanded]="isOpen()"
|
|
4227
|
+
[attr.aria-controls]="optionsId"
|
|
4228
|
+
[attr.aria-activedescendant]="activeOptionId()"
|
|
4229
|
+
aria-autocomplete="list" />
|
|
4126
4230
|
</sh-form-field>
|
|
4127
4231
|
</div>
|
|
4128
4232
|
|
|
@@ -4130,7 +4234,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImpor
|
|
|
4130
4234
|
class="options"
|
|
4131
4235
|
#optionsRef
|
|
4132
4236
|
(click)="close('active')"
|
|
4133
|
-
[class.searching]="searchable() && inputValue() !== ''"
|
|
4237
|
+
[class.searching]="searchable() && inputValue() !== ''"
|
|
4238
|
+
role="listbox"
|
|
4239
|
+
[id]="optionsId"
|
|
4240
|
+
[attr.aria-activedescendant]="activeOptionId()">
|
|
4134
4241
|
<ng-content select="[menu]" />
|
|
4135
4242
|
</div>
|
|
4136
4243
|
</sh-popover>
|
|
@@ -4142,7 +4249,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImpor
|
|
|
4142
4249
|
'[class.multi-layer]': 'asMultiLayer()',
|
|
4143
4250
|
},
|
|
4144
4251
|
}]
|
|
4145
|
-
}], propDecorators: { asMultiLayer: [{ type: i0.Input, args: [{ isSignal: true, alias: "asMultiLayer", required: false }] }], openIndicator: [{ type: i0.Input, args: [{ isSignal: true, alias: "openIndicator", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], customOptionElementSelectors: [{ type: i0.Input, args: [{ isSignal: true, alias: "customOptionElementSelectors", required: false }] }], keepClickedOptionActive: [{ type: i0.Input, args: [{ isSignal: true, alias: "keepClickedOptionActive", required: false }] }], closeOnClick: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnClick", required: false }] }], isOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "isOpen", required: false }] }, { type: i0.Output, args: ["isOpenChange"] }], closed: [{ type: i0.Output, args: ["closed"] }], searchable: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchable", required: false }] }], inputRef: [{ type: i0.ViewChild, args: ['inputRef', { isSignal: true }] }], optionsRef: [{ type: i0.ViewChild, args: ['optionsRef', { isSignal: true }] }]
|
|
4252
|
+
}], propDecorators: { asMultiLayer: [{ type: i0.Input, args: [{ isSignal: true, alias: "asMultiLayer", required: false }] }], openIndicator: [{ type: i0.Input, args: [{ isSignal: true, alias: "openIndicator", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], customOptionElementSelectors: [{ type: i0.Input, args: [{ isSignal: true, alias: "customOptionElementSelectors", required: false }] }], keepClickedOptionActive: [{ type: i0.Input, args: [{ isSignal: true, alias: "keepClickedOptionActive", required: false }] }], closeOnClick: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnClick", required: false }] }], isOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "isOpen", required: false }] }, { type: i0.Output, args: ["isOpenChange"] }], closed: [{ type: i0.Output, args: ["closed"] }], searchable: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchable", required: false }] }], inputRef: [{ type: i0.ViewChild, args: ['inputRef', { isSignal: true }] }], optionsRef: [{ type: i0.ViewChild, args: ['optionsRef', { isSignal: true }] }], onShipMenuOpen: [{
|
|
4253
|
+
type: HostListener,
|
|
4254
|
+
args: ['ship-menu-open', ['$event']]
|
|
4255
|
+
}] } });
|
|
4146
4256
|
|
|
4147
4257
|
class ShipProgressBar {
|
|
4148
4258
|
constructor() {
|
|
@@ -6913,14 +7023,22 @@ class ShipTooltipWrapper {
|
|
|
6913
7023
|
if (this.isOpen()) {
|
|
6914
7024
|
setTimeout(() => {
|
|
6915
7025
|
this.#selfRef.nativeElement.showPopover();
|
|
6916
|
-
this.
|
|
7026
|
+
this.schedulePositionUpdate();
|
|
6917
7027
|
});
|
|
6918
7028
|
}
|
|
6919
7029
|
else {
|
|
6920
7030
|
this.#selfRef.nativeElement.hidePopover();
|
|
6921
7031
|
}
|
|
6922
7032
|
}, ...(ngDevMode ? [{ debugName: "openEffect" }] : []));
|
|
7033
|
+
this.rafId = null;
|
|
7034
|
+
this.schedulePositionUpdate = () => {
|
|
7035
|
+
if (this.rafId !== null) {
|
|
7036
|
+
cancelAnimationFrame(this.rafId);
|
|
7037
|
+
}
|
|
7038
|
+
this.rafId = requestAnimationFrame(this.calculateTooltipPosition);
|
|
7039
|
+
};
|
|
6923
7040
|
this.calculateTooltipPosition = () => {
|
|
7041
|
+
this.rafId = null;
|
|
6924
7042
|
if (!this.anchorEl())
|
|
6925
7043
|
return;
|
|
6926
7044
|
const hostRect = this.anchorEl().nativeElement.getBoundingClientRect();
|
|
@@ -6928,23 +7046,38 @@ class ShipTooltipWrapper {
|
|
|
6928
7046
|
const tooltipRect = tooltipEl.getBoundingClientRect();
|
|
6929
7047
|
if (tooltipRect.width === 0 && tooltipRect.height === 0)
|
|
6930
7048
|
return;
|
|
6931
|
-
|
|
6932
|
-
|
|
6933
|
-
|
|
6934
|
-
|
|
6935
|
-
let newTop = hostRect.top - tooltipRect.height;
|
|
6936
|
-
let newLeft = hostRect.left + hostRect.width / 2 - tooltipRect.width / 2;
|
|
6937
|
-
if (outOfBoundsTop) {
|
|
6938
|
-
newTop = hostRect.top + hostRect.height;
|
|
7049
|
+
if (this.SUPPORTS_ANCHOR) {
|
|
7050
|
+
const isPlacedBelow = tooltipRect.top > hostRect.top;
|
|
7051
|
+
if (this.isBelow() !== isPlacedBelow) {
|
|
7052
|
+
this.isBelow.set(isPlacedBelow);
|
|
6939
7053
|
}
|
|
6940
|
-
|
|
6941
|
-
|
|
6942
|
-
|
|
6943
|
-
|
|
6944
|
-
|
|
6945
|
-
|
|
6946
|
-
|
|
6947
|
-
|
|
7054
|
+
return;
|
|
7055
|
+
}
|
|
7056
|
+
const gap = 12;
|
|
7057
|
+
const outOfBoundsTop = hostRect.top - tooltipRect.height - gap < 0;
|
|
7058
|
+
if (this.isBelow() !== outOfBoundsTop) {
|
|
7059
|
+
this.isBelow.set(outOfBoundsTop);
|
|
7060
|
+
}
|
|
7061
|
+
let newTop = hostRect.top - tooltipRect.height - gap;
|
|
7062
|
+
let newLeft = hostRect.left + hostRect.width / 2 - tooltipRect.width / 2;
|
|
7063
|
+
if (outOfBoundsTop) {
|
|
7064
|
+
newTop = hostRect.top + hostRect.height;
|
|
7065
|
+
}
|
|
7066
|
+
if (newLeft + tooltipRect.width > window?.innerWidth) {
|
|
7067
|
+
newLeft = hostRect.right - tooltipRect.width / 2;
|
|
7068
|
+
}
|
|
7069
|
+
if (newLeft < 0) {
|
|
7070
|
+
newLeft = -(tooltipRect.width / 2);
|
|
7071
|
+
}
|
|
7072
|
+
const leftStyle = `${newLeft}px`;
|
|
7073
|
+
const topStyle = `${newTop}px`;
|
|
7074
|
+
if (tooltipEl.style.left !== leftStyle) {
|
|
7075
|
+
this.#renderer.setStyle(tooltipEl, 'left', leftStyle);
|
|
7076
|
+
}
|
|
7077
|
+
if (tooltipEl.style.top !== topStyle) {
|
|
7078
|
+
this.#renderer.setStyle(tooltipEl, 'top', topStyle);
|
|
7079
|
+
}
|
|
7080
|
+
if (tooltipEl.style.position !== 'fixed') {
|
|
6948
7081
|
this.#renderer.setStyle(tooltipEl, 'position', 'fixed');
|
|
6949
7082
|
}
|
|
6950
7083
|
};
|
|
@@ -6954,13 +7087,20 @@ class ShipTooltipWrapper {
|
|
|
6954
7087
|
#positionAbort;
|
|
6955
7088
|
ngAfterViewInit() {
|
|
6956
7089
|
this.#positionAbort = new AbortController();
|
|
6957
|
-
const options = { signal: this.#positionAbort.signal, capture: true };
|
|
6958
|
-
window?.addEventListener('scroll', this.
|
|
6959
|
-
window?.addEventListener('resize', this.
|
|
6960
|
-
|
|
7090
|
+
const options = { signal: this.#positionAbort.signal, capture: true, passive: true };
|
|
7091
|
+
window?.addEventListener('scroll', this.schedulePositionUpdate, options);
|
|
7092
|
+
window?.addEventListener('resize', this.schedulePositionUpdate, {
|
|
7093
|
+
signal: this.#positionAbort.signal,
|
|
7094
|
+
passive: true,
|
|
7095
|
+
});
|
|
7096
|
+
this.schedulePositionUpdate();
|
|
6961
7097
|
}
|
|
6962
7098
|
ngOnDestroy() {
|
|
6963
7099
|
this.#positionAbort?.abort();
|
|
7100
|
+
if (this.rafId !== null) {
|
|
7101
|
+
cancelAnimationFrame(this.rafId);
|
|
7102
|
+
this.rafId = null;
|
|
7103
|
+
}
|
|
6964
7104
|
}
|
|
6965
7105
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: ShipTooltipWrapper, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
6966
7106
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.0", 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 }, content: { classPropertyName: "content", publicName: "content", isSignal: true, isRequired: false, transformFunction: null }, close: { classPropertyName: "close", publicName: "close", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "tooltip" }, properties: { "attr.popover": "\"manual\"", "style.position-anchor": "positionAnchorName()", "class.below": "isBelow()" } }, ngImport: i0, template: `
|
|
@@ -7012,7 +7152,7 @@ class ShipTooltip {
|
|
|
7012
7152
|
this.#elementRef = inject((ElementRef));
|
|
7013
7153
|
this.#viewContainerRef = inject(ViewContainerRef);
|
|
7014
7154
|
this.#environmentInjector = inject(EnvironmentInjector);
|
|
7015
|
-
this
|
|
7155
|
+
this.debounceTimer = null;
|
|
7016
7156
|
this.DEBOUNCE_DELAY = 500;
|
|
7017
7157
|
this.anchorName = `--${generateUniqueId()}`;
|
|
7018
7158
|
this.isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : []));
|
|
@@ -7021,7 +7161,6 @@ class ShipTooltip {
|
|
|
7021
7161
|
#elementRef;
|
|
7022
7162
|
#viewContainerRef;
|
|
7023
7163
|
#environmentInjector;
|
|
7024
|
-
#renderer;
|
|
7025
7164
|
onMouseEnter() {
|
|
7026
7165
|
if (openRef?.component.anchorName !== this.anchorName) {
|
|
7027
7166
|
this.cleanupTooltip();
|
|
@@ -7080,6 +7219,10 @@ class ShipTooltip {
|
|
|
7080
7219
|
cleanupTooltip() {
|
|
7081
7220
|
if (openRef?.wrapperComponentRef) {
|
|
7082
7221
|
openRef.component.cancelCleanupTimer();
|
|
7222
|
+
const nativeEl = openRef.wrapperComponentRef.location.nativeElement;
|
|
7223
|
+
if (nativeEl && typeof nativeEl.matches === 'function' && nativeEl.matches(':popover-open')) {
|
|
7224
|
+
nativeEl.hidePopover();
|
|
7225
|
+
}
|
|
7083
7226
|
openRef.wrapperComponentRef.destroy();
|
|
7084
7227
|
openRef.component.isOpen.set(false);
|
|
7085
7228
|
openRef = null;
|